子线程和Handler引起的内存泄漏及解决
子线程
new Thread(new Runnable() { @Override public void run() { } }).start();两点内存泄漏
第一点 匿名内部类会隐式包含外部类的引用 如果Activity意外退出了 就不要指望Activity能够被回收
怎么解决 内部写一个静态内部类Thread 静态的不会包含外部类的引用
new MyThread().start(); } static class MyThread extends Thread { @Override public void run() { //耗时操作 } }
可是如果想要外部类的内容呢???不是又需要外部类的引用了?如果外部类的实例进来不是又重蹈覆辙了?所以需要弱引用。弱引用在每一次垃圾收集器工作的时候,都会被回收
new MyThread(this).start(); } static class MyThread extends Thread { WeakReference<MainActivity> weakReference; public MyThread(MainActivity mainActivity) { weakReference = new WeakReference<>(mainActivity); } @Override public void run() { //耗时操作 } }
Activity的内存泄漏基本解决了,但是线程依然无法被回收,而且DVM会永久保留这个线程。解决方法是简单设置一个标记位就可以了
mThread = new MyThread(this); mThread.start(); } MyThread mThread; @Override protected void onDestroy() { super.onDestroy(); mThread.close(); } static class MyThread extends Thread { WeakReference<MainActivity> weakReference; private boolean mRunning = false; public MyThread(MainActivity mainActivity) { weakReference = new WeakReference<>(mainActivity); } @Override public void run() { mRunning = true; while (mRunning) { //耗时操作 } } public void close() { mRunning = false; } }
圆满了
下面是Handler
这一通警告,就是,as编译器发出的警告。看看这个匿名内部类也是可以直接访问外部类成员的。解决方式,简单的多了,直接在onDestory的时候,
TextView tv; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { tv.setText("111"); super.handleMessage(msg); } }; @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); }直接把队列中的msg全部移除。他内存泄漏的原因是,那种延时发送的消息,message的target字段会维护这个Handler,而Handler内部会隐式维护Activity导致Activity无法释放。当然你也可以像Thread处理的一样去做。