Detects Anonymous class implements Android.content.dialoginterfaces$onclicklistener with the leak Canary tool
Google's, found an article https://corner.squareup.com/2015/08/a-small-leak.html
Large paragraph of the English expression is not interested to see, but also do not understand, so we have to pull down to the fix section:
The Startup Fix
Support for only devices this use the ART VM, ie Android 5+. No more bugs! Also, no more users.
The Won ' t Fix
You could also assume that these leaks would have a limited impact and so you had better things to do, or maybe simpler Leaks to fix. Leakcanary ignores all Message
leaks by default. Beware though, an activity holds it entire view hierarchy in memory and can retain several megabytes.
The App fix
Make sure your DialogInterface.OnClickListener
instances don't hold strong references to activity instances, for example by clearing the reference The Listener when the dialog window is detached. Here's a wrapper class to make it easy:
Copy the following class directly
Public Final classDetachableclicklistenerImplementsDialoginterface.onclicklistener { Public StaticDetachableclicklistener Wrap (Dialoginterface.onclicklistener delegate) {return NewDetachableclicklistener (delegate); } PrivateDialoginterface.onclicklistener Delegateornull; PrivateDetachableclicklistener (Dialoginterface.onclicklistener delegate) { This. Delegateornull =delegate; } @Override Public voidOnClick (Dialoginterface Dialog,intwhich) { if(Delegateornull! =NULL) {Delegateornull.onclick (dialog, which); } } Public voidClearondetach (Dialog Dialog) {Dialog.getwindow (). Getdecorview (). Getviewtreeobserver (). Add Onwindowattachlistener (NewOnwindowattachlistener () {@Override Public voidonwindowattached () {} @Override Public voidonwindowdetached () {delegateornull=NULL; } }); }}
Then you can just wrap all OnClickListener
instances:
In the class that you want to use for Alertdialog, add:
Detachableclicklistener Clicklistener = detachableclicklistener.wrap (New Dialoginterface.onclicklistener () { @Override Public voidOnClick (Dialoginterface Dialog,intwhich) {//MyActivity.this.makeCroissants (); //dealing with things in Positivebutton.} }); Alertdialog Dialog=NewAlertdialog.builder ( This). Settitle (""). Setmessage (""). Setpositivebutton ("Baguette", clicklistener). Setnegativebutton (GetString (r.string.update_later),NewDialoginterface.onclicklistener () {@Override Public voidOnClick (Dialoginterface Dialog,intwhich) {Dialog.dismiss (); }}). Create ();d ialog.show (); //Put Show () behind clear in the original text, will errorClicklistener.clearondetach (dialog);
The Plumber ' s Fix
Flush your worker threads on a regular basis:send a empty message when a HandlerThread
becomes idle to make sure no message leaks For long.
Static voidFlushstacklocalleaks (Looper Looper) {FinalHandler Handler =NewHandler (Looper); Handler.post (NewRunnable () {@Override Public voidrun () {looper.myqueue (). Addidlehandler (NewMessagequeue.idlehandler () {@Override Public BooleanQueueidle () {handler.sendmessagedelayed (), Handler.obtainmessage (),1000); return true; } }); } });}
This is a useful for libraries, because you can ' t control what developers be going to does with dialogs. We used it in Picasso, with a similar fix for other types of worker threads.
Dialoginterface Memory leak Anonymous class implements Android.content.dialoginterfaces$onclicklistener