2017-12-15 4 views
0

Ich bekomme ein Speicherleck auf Android von LeakCanary berichtet, aber ich kann nicht herausfinden, wie man es verfolgen.Verfolgen von Speicherleck von LeakCanary auf Android gemeldet

Ich habe eine Aktivität namens Splash, die einen Dienst ruft, um Konfigurationsdaten abzurufen, und dann über einen Handler pingt zurück zu der Aktivität.

//Started like this in the Splash activity 
ConfigDumpService.start(this, this, BaseService.DATA_CALLBACK_ACTION_SIMPLE); 

, wo die Startmethode ist:

public static void start(final Context context, final Handler.Callback handlerCallback, final int callbackAction) { 
    final Messenger messenger = new Messenger(new Handler(handlerCallback)); 
    final Intent intent = new Intent(context, ConfigDumpService.class); 
    intent.putExtra(BaseService.PARAM_MESSENGER, messenger); 
    intent.putExtra(BaseService.PARAM_CALLBACK_ACTION, callbackAction); 
    context.startService(intent); 
} 

Die Aktivität Splash implementiert Handler.Callback

@Override 
public boolean handleMessage(final Message msg) { 
    L.p("In Splash handleMessage(), thread: " + Thread.currentThread().getName()); 

    if (BaseService.DATA_RETRIEVE_SUCCESS == msg.arg1) { 
     L.p("Message from ConfigService service is SUCCESS!"); 
     startApp(); 
    } else { 
     L.p("Message from ConfigService service is FAIL!"); 
     showCannotContinueDialog(); 
    } 
    return true; 
} 

Die ConfigDumpService

// Previously fetched some data... 

final Message message = Message.obtain(); 
message.setData(bundle); 

if (successful) { 
    message.arg1 = BaseService.DATA_RETRIEVE_SUCCESS; 
} else { 
    message.arg1 = BaseService.DATA_RETRIEVE_FAIL; 
} 

try { 
    final Messenger messenger = startIntent.getParcelableExtra(BaseService.PARAM_MESSENGER); 
    messenger.send(message); 
} catch (RemoteException e) { 
    L.p("In onHandleIntent RemoteException"); 
    e.printStackTrace(); 
} 

stopSelf(); 

Ein weiterer Ort, an dem ein Handler creat ist In der Splash-Aktivität wird gestartet, um die Hauptaktivität nach einer kleinen Verzögerung zu starten:

Der Aufruf-Stack ist nicht sehr hilfreich. Ich würde mich über irgendwelche Tipps freuen.

Dank

enter image description here

+0

Ohne Code gibt es keine Möglichkeit, die wir beantworten können. Wie erhält (und speichert) Ihr Dienst eine Möglichkeit, die Aktivität aufzurufen? Wo ist diese Referenz aufgeräumt? –

+0

Einverstanden, ein [mcve] würde helfen, insbesondere diese "Splash" -Aktivität und diesen 'Handler' zu zeigen. – CommonsWare

+0

@CommonsWare Code hinzugefügt. Vielen Dank. – zundi

Antwort

1

Ich denke, es zu engen Zusammenhang steht, wie Sie Ihre Handler instanziiert. Da Sie die Handler.Callback in Ihrem SplashActivity implementieren, halten Sie eine harte Referenz in Ihrer Nachrichtenwarteschlange. Stattdessen sollten Sie Ihre eigene Handler Klasse implementieren und wenn es eine innere Klasse ist, sollte es static sein. Und innerhalb dieser Gewohnheit Handler sollten Sie eine WeakReference zu der Activity haben, die Sie überschreiten. This Pfosten erklärt das Problem im Detail und zeigt Ihnen, wie man dieses Problem löst. Hoffe, das hilft;)

+0

Aus reiner Neugier, sobald die Methode onHandle() beendet wird, würde die SplashActivity diese Referenz verlieren und wäre für die GC'ed verfügbar, oder? Oder würde die Referenz der Aktivität für immer in der Nachrichtenwarteschlange stehen? – zundi

Verwandte Themen