源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Android中Handler引起的内存泄露问题解决办法

  • 时间:2020-01-26 06:03 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Android中Handler引起的内存泄露问题解决办法
在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用。通常我们的代码会这样实现。
[url=http://www.1sucai.cn/article/59894.htm]Java:”失效”的private修饰符 [/url] 确实上面的代码示例有点难以察觉内存泄露,那么下面的例子就非常明显了
[u]复制代码[/u] 代码如下:
public class SampleActivity extends Activity {   private final Handler mLeakyHandler = new Handler() {     @Override     public void handleMessage(Message msg) {       // ...     }   }   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     // Post a message and delay its execution for 10 minutes.     mLeakyHandler.postDelayed(new Runnable() {       @Override       public void run() { /* ... */ }     }, 1000 * 60 * 10);     // Go back to the previous Activity.     finish();   } }
分析一下上面的代码,当我们执行了Activity的finish方法,被延迟的消息会在被处理之前存在于主线程消息队列中10分钟,而这个消息中又包含了Handler的引用,而Handler是一个匿名内部类的实例,其持有外面的SampleActivity的引用,所以这导致了SampleActivity无法回收,进行导致SampleActivity持有的很多资源都无法回收,这就是我们常说的内存泄露。 注意上面的new Runnable这里也是匿名内部类实现的,同样也会持有SampleActivity的引用,也会阻止SampleActivity被回收。 要解决这种问题,思路就是不适用非静态内部类,继承Handler时,要么是放在单独的类文件中,要么就是使用静态内部类。因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露。当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。注意:一个静态的匿名内部类实例不会持有外部类的引用。 修改后不会导致内存泄露的代码如下:
[u]复制代码[/u] 代码如下:
public class SampleActivity extends Activity {   /**    * Instances of static inner classes do not hold an implicit    * reference to their outer class.    */   private static class MyHandler extends Handler {     private final WeakReference<SampleActivity> mActivity;     public MyHandler(SampleActivity activity) {       mActivity = new WeakReference<SampleActivity>(activity);     }     @Override     public void handleMessage(Message msg) {       SampleActivity activity = mActivity.get();       if (activity != null) {         // ...       }     }   }   private final MyHandler mHandler = new MyHandler(this);   /**    * Instances of anonymous classes do not hold an implicit    * reference to their outer class when they are "static".    */   private static final Runnable sRunnable = new Runnable() {       @Override       public void run() { /* ... */ }   };   @Override   protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     // Post a message and delay its execution for 10 minutes.     mHandler.postDelayed(sRunnable, 1000 * 60 * 10);     // Go back to the previous Activity.     finish();   } }
其实在Android中很多的内存泄露都是由于在Activity中使用了非静态内部类导致的,就像本文提到的一样,所以当我们使用时要非静态内部类时要格外注意,如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。个人倾向于使用文章的静态类和弱引用的方法解决这种问题。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部