标签:
用Leak Canary工具检测到anonymous class implements android.content.DialogInterfaces$OnClickListener
谷歌之,找到一篇文章https://corner.squareup.com/2015/08/a-small-leak.html
大段大段的英文表示没兴趣看,也看不太懂,于是咱家就一直往下拉,到fix部分:
Support only devices that use the ART VM, ie Android 5+. No more bugs! Also, no more users.
You could also assume that these leaks will have a limited impact and that you have better things to do, or maybe simpler leaks to fix. LeakCanary ignores all Message
leaks by default. Beware though, an activity holds its entire view hierarchy in memory and can retain several megabytes.
Make sure your DialogInterface.OnClickListener
instances do not hold strong references to activity instances, for example by clearing the reference to the listener when the dialog window is detached. Here’s a wrapper class to make it easy:
直接复制下面这个类
public final class DetachableClickListener implements DialogInterface.OnClickListener { public static DetachableClickListener wrap(DialogInterface.OnClickListener delegate) { return new DetachableClickListener(delegate); } private DialogInterface.OnClickListener delegateOrNull; private DetachableClickListener(DialogInterface.OnClickListener delegate) { this.delegateOrNull = delegate; } @Override public void onClick(DialogInterface dialog, int which) { if (delegateOrNull != null) { delegateOrNull.onClick(dialog, which); } } public void clearOnDetach(Dialog dialog) { dialog.getWindow() .getDecorView() .getViewTreeObserver() .addOnWindowAttachListener(new OnWindowAttachListener() { @Override public void onWindowAttached() { } @Override public void onWindowDetached() { delegateOrNull = null; } }); } }
Then you can just wrap all OnClickListener
instances:
在要用到AlertDialog的类中添加:
DetachableClickListener clickListener = DetachableClickListener.wrap(new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // MyActivity.this.makeCroissants(); //处理PositiveButton中的事情 } }); AlertDialog dialog = new AlertDialog.Builder(this) .setTitle("") .setMessage("") .setPositiveButton("Baguette", clickListener) .setNegativeButton(getString(R.string.update_later), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create(); dialog.show(); //原文中把show()放在clear后面,会报错 clickListener.clearOnDetach(dialog);
Flush your worker threads on a regular basis: send an empty message when a HandlerThread
becomes idle to make sure no message leaks for long.
static void flushStackLocalLeaks(Looper looper) { final Handler handler = new Handler(looper); handler.post(new Runnable() { @Override public void run() { Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { handler.sendMessageDelayed(handler.obtainMessage(), 1000); return true; } }); } }); }
This is useful for libraries, because you can’t control what developers are going to do with dialogs. We used it in Picasso, with a similar fix for other types of worker threads.
DialogInterface内存泄露 anonymous class implements android.content.DialogInterfaces$OnClickListener
标签:
原文地址:http://www.cnblogs.com/carrieLee/p/5396534.html