版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36707431/article/details/78616900
一、Handler 和 Runnable 都有定时器的功能,当它们作为非静态内部类的时候,同样会持有外部类的引用,如果它们的内部有延迟操作,在延迟操作还没有发生的时候,销毁了外部类,那么外部类对象无法回收,从而造成内存泄漏。
假设MianActivity里面有个Handler的10秒延时操作:
Handler 和 Runnable 作为匿名内部类,都会持有 MainActivity 的引用,而它们内部有一个 10 秒钟的定时器,如果在打开 MainActivity 的 10 秒内关闭了 MainActivity,那么由于 Handler 和 Runnable 的生命周期比 MainActivity 长,会导致 MainActivity 无法被回收,从而造成内存泄漏。
二、应该如何避免内存泄漏呢?
一般套路就是把 Handler 和 Runnable 定义为静态内部类,这样它们就不再持有 MainActivity 的引用了,从而避免了内存泄漏:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Handler handler; private Runnable runnable; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new TestHandler(); runnable = new TestRunnable(); handler.postDelayed(runnable, 10 * 1000); } private static class TestHandler extends Handler { } private static class TestRunnable implements Runnable { @Override public void run() { Log.d(TAG, "run: "); } } }
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacks(runnable);
}
还有一种特殊情况,如果 Handler 或者 Runnable 中持有 Context 对象,那么即使使用静态内部类,还是会发生内存泄漏,这种情况可以使用弱引用的方式来引用 Context 来避免内存泄漏
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Handler handler;
private Runnable runnable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new TestHandler(new WeakReference<Context>(this));
runnable = new TestRunnable();
handler.postDelayed(runnable, 10 * 1000);
}
private static class TestHandler extends Handler {
private Context context;
private TestHandler(WeakReference<Context> weakContext) {
context = weakContext.get();
}
}
private static class TestRunnable implements Runnable {
@Override
public void run() {
Log.d(TAG, "run: ");
}
}
}