2016-08-11 6 views
0

Zunächst zu implementieren i setze mir eine einfache Aufgabe, eine Funktion auszuführen, mit Verzögerung zu machen. Zuerst machte ich ein lauffähiges und ausgeführt mit new Thread(runnable).start();, aber ich habe gelesen, dass nicht-statische innere Klassen zu Speicherlecks führen können, so habe ich versuchte Runnable als statisch zu machen.(Android) atempting statische WeakReference runnable

Ich folgte Beispiel in Is this Runnable safe from memory leak? und endete mit diesem Code:

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); 
      } 
     } 
    } 
} 

ich nicht vertraut bin mit inneren Klassen und Referenzierung, so dass trotz meines Code zu funktionieren scheint, ich bin nicht sicher, wenn ich suceeded mit mein Ziel, Speicherlecks zu vermeiden. So würde ich schätzen, wenn jemand meinen Code ansehen könnte.

+1

Nicht wirklich Lösung, aber Sie können Speicherverlust erheblich reduzieren, wenn Sie AplicationContext anstelle von Aktivität verwenden - auf diese Weise, selbst wenn Leckage passieren wird es keine visuellen Ressourcen im Speicher halten – X3Btel

+0

Ahh, ich sehe. Wenn ich also ApplicationContext verwende, um meine ApproxManager-Klasse zu instanziieren, wird meine übergeordnete Aktivität als Garbage Collected erfasst, selbst wenn der ApplixManager die Aktivität überlebt? – aphelion

+0

Ja, wenn Sie AplicationContext verwenden, wird ApproachManager keine Referenz auf die Aktivität halten – X3Btel

Antwort

2

Ihr Code sieht gut IMHO. Ich denke, Sie haben es geschafft, Sie runnable zu implementieren und sich gegen ein Speicherleck zu schützen.

Non - statische innere Klassen halten einen impliziten Hinweis auf die Instanz, die sie erstellt hat. Dies bedeutet, dass Sie, wenn Sie mit dem nicht statischen Ansatz fortfahren, einen Verweis auf eine ApproxManager Instanz speichern, und diese Instanz wird nicht als Garbage Collection behandelt. Die ApproxManager behält einen Verweis auf die Context und AlarmManager Instanzen und sie werden nicht Müll gesammelt werden, und dies ist Ihr Speicherleck.

Statische innere Klassen enthalten keine impliziten Verweise, aber sie können nicht auf nicht statische Member zugreifen. Daher müssen Sie alle erforderlichen Abhängigkeiten angeben, damit die Klasse ihre Arbeit verrichten kann. Mit der Verwendung von WeakReference verhindern Sie nicht die eventuelle Garbage-Collection der Variablen, falls eine benötigt wird.

+0

Vielen Dank für die Überprüfung meines Codes und für diese gute Erklärung – aphelion