2016-08-11 10 views
0

まず、私は自分自身を遅延を伴って実行するための簡単なタスクに設定しました。最初は実行可能ファイルを作成してnew Thread(runnable).start();で実行しましたが、非静的な内部クラスがメモリリークを引き起こす可能性があるので、私はRunnableを静的にしようとしました。(Android)静的ウィークリファレンスランタイムを実装しようとしています

私はIs this Runnable safe from memory leak?の例に続き、このコードで終了しました:

public class ApproxManager { 
    private Context mContext; 
    private AlarmManager mAlarmManager; 

    public ApproxManager(Context context){ 
     mContext = context; 
     mAlarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 
    } 

    public void setPeriod(int type, long when, int extendCount){ 
     Intent i = new Intent(mContext, OnAlarmReceiver.class); 
     long alarmtime = when; 
     i.putExtra(RReminder.PERIOD_TYPE, type); 
     i.putExtra(RReminder.EXTEND_COUNT, extendCount); 
     i.setAction(RReminder.CUSTOM_INTENT_APPROXIMATE_PERIOD_END); 
     PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); 
     new Thread(new WeakRunnable(mContext, alarmtime,pi)).start(); 
    } 

    public void setAlarm(long alarmTime, PendingIntent pi){ 
     mAlarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi); 
    } 

    private static final class WeakRunnable implements Runnable { 
     private final WeakReference<Context> mContext; 
     long mAlarmtime; 
     PendingIntent mpi; 

     protected WeakRunnable(Context context, long alarmtime, PendingIntent pi){ 
     mContext = new WeakReference<Context>(context); 
     mAlarmtime = alarmtime; 
     mpi = pi; 

     } 

     @Override 
     public void run() { 
      Context context = mContext.get(); 
      if (context != null) { 
       try { 
        Thread.sleep(1500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       ApproxManager approxManager = new ApproxManager(context); 
       approxManager.setAlarm(mAlarmtime,mpi); 
      } 
     } 
    } 
} 

私は内部クラスと参照に慣れていないよ、私のコードにもかかわらず、動作しているように見えるので、私はとsuceededしている場合、私は、わかりません私の目標はメモリリークを避けることです。だから誰かが私のコードを見ることができたらうれしいです。

+1

実際には解決策ではありますが、アクティビティの代わりにAplicationContextを使用すると、メモリリークを大幅に減らすことができます。つまり、リークが発生してもメモリ内にビジュアルリソースが保持されません。 – X3Btel

+0

ああ、そうです。したがって、ApproxManagerクラスをインスタンス化するためにApplicationContextを使用すると、ApproxManagerがアクティビティを超えても親アクティビティがガベージコレクションされます。 – aphelion

+0

はい、AplicationContextを使用している場合、ApproxManagerはアクティビティへの参照を保持しません – X3Btel

答えて

2

あなたのコードはIMHOのように見えます。私はあなたが正常にあなたを実行可能に実装し、メモリリークから身を守ることができたと思います。

非静的な内部クラスは、それらを作成したインスタンスへの暗黙の参照を保持します。これは、非静的アプローチを使用すると、ApproxManagerインスタンスへの参照を保持し、このインスタンスがガベージコレクションされないことを意味します。 ApproxManagerは、ContextAlarmManagerのインスタンスへの参照を保持しています。どちらもガベージコレクションされません。これはメモリリークです。

静的内部クラスは暗黙的参照を保持しませんが、非静的メンバーにはアクセスできません。そのため、必要なすべての依存関係を提供する必要があります。 WeakReferenceを使用すると、変数が必要な場合に、変数の最終的なガベージコレクションを防ぐことはできません。

+0

私のコードをチェックしていただきありがとうございました。 – aphelion

関連する問題