Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // do something. } }
当我们这样创建`Handler`的时候`Android Lint`会提示我们这样一个`warning: In Android, Handler classes should be static or leaks might occur.`。
一直以来没有仔细的去分析泄露的原因,先把主要原因列一下:
- `Android`程序第一次创建的时候,默认会创建一个`Looper`对象,`Looper`去处理`Message Queue`中的每个`Message`,主线程的`Looper`存在整个应用程序的生命周期.
- `Hanlder`在主线程创建时会关联到`Looper`的`Message Queue`,`Message`添加到消息队列中的时候`Message(排队的Message)`会持有当前`Handler`引用,当`Looper`处理到当前消息的时候,会调用`Handler#handleMessage(Message)`.就是说在`Looper`处理这个`Message`之前,会有一条链`MessageQueue -> Message -> Handler -> Activity`,由于它的引用导致你的`Activity`被持有引用而无法被回收`
- **在java中,no-static的内部类会隐式的持有当前类的一个引用。static的内部类则没有。**
public class SampleActivity extends Activity { private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { // do something } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 发送一个10分钟后执行的一个消息 mHandler.postDelayed(new Runnable() { @Override public void run() { } }, 600000); // 结束当前的Activity finish(); }
在`finish()`的时候,该`Message`还没有被处理,`Message`持有`Handler`,`Handler`持有`Activity`,这样会导致该`Activity`不会被回收,就发生了内存泄露.
解决方法
- 通过程序逻辑来进行保护。
- 如果`Handler`中执行的是耗时的操作,在关闭`Activity`的时候停掉你的后台线程。线程停掉了,就相当于切断了`Handler`和外部连接的线,`Activity`自然会在合适的时候被回收。
- 如果`Handler`是被`delay`的`Message`持有了引用,那么在`Activity`的`onDestroy()`方法要调用`Handler`的`remove*`方法,把消息对象从消息队列移除就行了。
- 关于`Handler.remove*`方法
- `removeCallbacks(Runnable r)` ——清除r匹配上的Message。
- `removeC4allbacks(Runnable r, Object token)` ——清除r匹配且匹配token(Message.obj)的Message,token为空时,只匹配r。
- `removeCallbacksAndMessages(Object token)` ——清除token匹配上的Message。
- `removeMessages(int what)` ——按what来匹配
- `removeMessages(int what, Object object)` ——按what来匹配
我们更多需要的是清除以该`Handler`为`target`的所有`Message(Callback)`就调用如下方法即可`handler.removeCallbacksAndMessages(null)`;
- 将`Handler`声明为静态类。
静态类不持有外部类的对象,所以你的`Activity`可以随意被回收。但是不持有`Activity`的引用,如何去操作`Activity`中的一些对象? 这里要用到弱引用
public class MyActivity extends Activity { private MyHandler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new MyHandler(this); } @Override protected void onDestroy() { // Remove all Runnable and Message. mHandler.removeCallbacksAndMessages(null); super.onDestroy(); } static class MyHandler extends Handler { // WeakReference to the outer class's instance. private WeakReference<MyActivity> mOuter; public MyHandler(MyActivity activity) { mOuter = new WeakReference<MyActivity>(activity); } @Override public void handleMessage(Message msg) { MyActivity outer = mOuter.get(); if (outer != null) { // Do something with outer as your wish. } } } }
本文为转载,看源处请移步:
相关推荐
Handler 作为非静态内部类持有当前 Activity 的隐式引用,如果 Handler 没有被释放,其所持有的外部引用也就是 Activity 不可能被释放,导致内存泄漏。 Handler 内存泄漏的解决方法是使用静态内部类并继承 Handler...
解决Handler导致内存泄露的方法有两种: 方法一:通过程序逻辑来进行保护。 1. 在关闭Activity的时候停掉你的后台线程。线程停掉了,就相当于切断了Handler和外部连接的线,Activity自然会在合适的时候被回收。 2....
Android 中 Handler 造成内存泄露的分析及解决方法 什么是内存泄露? 在 Java 中,使用有向图机制,通过 GC 自动检查内存中的对象(什么时候检查由虚拟机决定),如果 GC 发现一个或一组对象为不可到达状态,则将...
因为Handler持有Activity的引用,只要Handler还存在,Activity就不会被回收,从而导致内存泄漏。 **1.2 原理解释** 在Java中,非静态内部类和匿名内部类会隐式地持有外部类的引用。上述例子中的`Handler`就是一个...
详细可参考博文:原创 android内存泄露:3、Handler的错误使用导致内存泄露 ,这篇文章我们将介绍:Toast的错误使用导致内存泄露 二、Toast的错误使用导致内存泄露 我们通常,连续点击按钮多次提示的 Toast,它...
异步线程中Handler的不当使用是导致内存泄露的常见原因。例如,Handler持有Activity的引用,但在Activity销毁后未能及时清除。 **解决策略**:确保Handler不持有Activity的强引用,可以使用WeakReference。 ##### ...
Handler 是 Android 中的一种机制,用于在不同的线程之间传递消息,但如果不正确地使用 Handler,可能会导致内存泄露。 在 Android 中,Handler 是一个很常用的机制,但它也很容易导致内存泄露。特别是在 Activity ...
当对象不再使用时,如果不及时清理,可能会导致内存泄漏。内存泄漏是指无用的对象由于仍然有引用链指向它们,而无法被垃圾回收器(GC)回收。Android的Dalvik VM有一个内置的GC机制,用于定期回收不再使用的内存,但...
2. **弱引用与Handler**:使用WeakReference包裹Handler实例,防止Handler导致Activity或Fragment的内存泄漏,因为弱引用不会阻止对象被垃圾回收。 3. **自定义Message子类**:有时候,为了增强消息的可读性和可...
在Android应用开发中,Handler、Looper和Message是实现线程间通信的重要机制,尤其是在...同时,需要注意的是,过度依赖Handler可能导致内存泄漏,因此在不再使用Handler时,记得及时移除引用,防止内存泄露的发生。
- 在SplashActivity的onDestroy或onPause方法中,调用`removeCallbacksAndMessages(null)`,以防止销毁活动时Runnable仍在后台运行,导致内存泄漏。 5. **注意事项**: - Splash Screen不宜过长,以免影响用户体验...
当`Handler`被绑定到Activity或Fragment等生命周期有限的对象时,如果不正确处理,可能导致内存泄漏。使用`WeakReference`可以避免这种情况: ```java class MyHandler extends Handler { private WeakReference...
在本次技术公开课中,讲师张权威将深入剖析Android平台下的内存泄漏案例,通过对一个具体案例的分析,展示内存泄漏的形成原因、诊断流程以及解决方案。 首先,案例中提到当连续多次打开应用时,界面出现卡顿,并且...
- 使用`Dominator Tree`、`Package`等视图分析内存使用情况,查找可能导致内存泄露的对象。 #### 三、内存泄露的分析技巧 - **Dominator Tree Package**:通过查看包内对象的引用关系,寻找可能的内存泄露源头。 ...
7. **Service、BroadcastReceiver、ContentObserver、Handler和Thread**: 这些组件如果不正确关闭,可能导致内存泄露。 **解决策略** 1. **谨慎使用Context**: 了解Context的不同类型(Application、Activity等),...
1. 避免内存泄漏:Handler的引用可能会导致Activity无法正常回收,因此在Activity的onDestroy()方法中应调用`removeCallbacksAndMessages(null)`,解除对Handler的引用。 2. 使用静态内部类的Handler:静态内部类...
如果 Handler 在 Activity 生命周期结束后没有被释放,可能会导致内存泄漏。 第六种可能:Thread 线程可能会导致内存泄漏,如果线程在 Activity 生命周期结束后没有被释放,可能会导致内存泄漏。 第七种可能:...
- 在静态成员中保存非静态成员的引用也会导致内存泄漏,因为静态成员的生命周期通常比非静态成员长得多。 4. **Bitmap对象管理不当**: - `Bitmap`对象占用大量内存,若不正确释放,很容易导致内存泄漏。 5. **...
然而,不当使用Handler,尤其是结合匿名内部类或非静态内部类,可能导致内存泄漏和Native内存增加,这对应用性能和稳定性造成负面影响。 首先,我们要理解内存泄漏的概念。内存泄漏是指程序中已分配的内存没有被...