2016-07-31 11 views
0

私は15時間かけて自分の記憶の問題を解決しようとしましたが、それに関するいくつかの質問を読んでいますが、本当に良い答えと解決策は見つかりません。ハンドラのメモリリーク

Handlerを使用してMediaPlayerの時刻がsetOnBufferingUpdateListenerから更新されるたびに、2つの整数を送信しています。整数を2つのTextViewに設定します。しかし、時間が更新されるたびに。 AndroidスタジオのAndroidモニターは、1メガバイト単位でメモリを増やしています。

私はそれを望んでいません。ここで私のクラス。

ハンドラ:

public class UpdateH extends android.os.Handler { 

private OnUpdate onUpdate; 

public UpdateH() { 
} 

public UpdateH(Callback callback) { 
    super(callback); 
} 

public UpdateH(Looper looper) { 
    super(looper); 
} 

public UpdateH(Looper looper, Callback callback) { 
    super(looper, callback); 
} 

@Override 
public void handleMessage(Message msg) { 
    onUpdate.update(msg.arg1, msg.arg2); 
} 

public void setOnUpdate(OnUpdate onUpdate) { 
    this.onUpdate = onUpdate; 
} 

public interface OnUpdate{ 
    void update(int cu, int t); 
} 

}

フラグメント:スレッドで

@Override 
public void onPause() { 
    super.onPause(); 
    Player.playerProgressHandler = null; 
    mu = null; 
} 

private UpdateH mu; 

@Override 
public void onResume() { 
    super.onResume(); 
    mu = new UpdateH(Looper.getMainLooper()); 

    mu.setOnUpdate(new UpdateH.OnUpdate() { 
     @Override 
     public void update(int cu, int t) { 
      setTime(cu, t); 
     } 
    }); 
    Player.playerProgressHandler = mu; 
} 

private void setTime(int current, int total){ 
    this.current.setText(String.format("%02d:%02d:%02d", 
      (int) ((current/(1000 * 60 * 60)) % 24), 
      (int) ((current/(1000 * 60)) % 60), 
      (int) (current/1000) % 60)); 

    this.total.setText(String.format("%02d:%02d:%02d", 
      (int) ((total/(1000 * 60 * 60)) % 24), 
      (int) ((total/(1000 * 60)) % 60), 
      (int) (total/1000) % 60)); 
} 

if(playerProgressHandler != null && mp != null && mp.isPlaying()){ 
        Message message = Message.obtain(); 
        message.setTarget(playerProgressHandler); 
        message.arg1 = mp.getCurrentPosition(); 
        message.arg2 = mp.getDuration(); 
        message.sendToTarget(); 
       } 

問題はのsetTimeメソッドから来ます。なぜ私はそれにコードをコメントする。メモリは冷たいままです。

注:AsyncTaskについて

答えて

-1

を思えばAsyncTaskはあなたがスレッドを実行している場合、それは必要としないならば、あなたは、あなたのonDestroy(または可能性onPauseまたはonStopでそれをキャンセルする必要がある、それを修正することはできません画面が表示されていないときに実行されています)、終了してガベージコレクションが実行されます。スレッドがガベージコレクションされると、テキストビューに残っている参照がなくなり、残りのアクティビティがガベージコレクションされます。 Runnableが終了していることを確認します。つまり、スレッドがメインループでキャンセルされたかどうかをチェックする必要があります。

自己参照ループでハンドラに投稿する場合、同じ場所にあるすべてのメッセージをハンドラから削除する必要があります。

そして、ちょうどあなたの全面的なアップデータは、必要以上に複雑です。

+0

私が言ったように、問題はスレッドに関するものではありません。整数は、MediaPlayer.setOnBufferingUpdateListenerコールバックによって送信されます。これはTextViewのsettextメソッドに関するものです。 – user3502626

+0

あなたは間違っている - それはスレッドについてです。スレッドはアクティビティが破棄された後も継続しますが、textviewを設定する呼び出しのためにアクティビティへの参照があります。これにより、アクティビティー全体および関連するすべてのビューおよび変数がリークします。スレッドを修正すると、リークが発生します。 –

+0

しかし、[MediaPlayerクラス](https://developer.android.com/reference/android/media/MediaPlayer.html)を使用しているため、スレッドを修正できません。私のコードは、MediaPlayerの時刻がsetOnBufferingUpdateListenerから更新されたときに呼び出されます。 **私はTextViewを更新するためのスレッドを作成しませんでした。そのスレッドはアンドロイドから来て、私は何もすることはできません。さらに、アクティビティを閉じるときにハンドラをnullに設定するため、アクティビティを閉じるときにコードが正常に動作するため、メモリが増えません。 – user3502626

0

今すぐ確認できます。私は数分間待つ。メモリは単独で減少します。それは、参照されていない変数をクリアするのは遅いだけです。