[转帖]Handler 引起的内存泄露_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 3522 | 回复: 0   主题: [转帖]Handler 引起的内存泄露        下一篇 
shuangqiang.xing
注册用户
等级:上尉
经验:737
发帖:64
精华:0
注册:2013-10-30
状态:离线
发送短消息息给shuangqiang.xing 加好友    发送短消息息给shuangqiang.xing 发消息
发表于: IP:您无权察看 2013-11-6 18:07:30 | [全部帖] [楼主帖] 楼主

当我们这样写在一个Activity中时,Android Lint会提示我们这样一个 warning: In Android, Handler classes should be static or leaks might occur.。
意思说:在Android中,Handler 类应该是静态的否则可能发生泄漏。

为什么会是这样呢?

了解一下Handler

  1. 当Android程序第一次创建的时候,在主线程同时会创建一个Looper对象。Looper实现了一个简单的消息队列,一个接着一个处理Message对象。程序框架所有主要的事件(例如:屏幕上的点击时间,Activity生命周期的方法等等)都包含在Message对象中,然后添加到Looper的消息队列中,一个一个处理。主线程的Looper存在整个应用程序的生命周期内。
  2. 当一个Handler对象在主线程中创建的时候��它会关联到Looper的 message queue。Message添加到消息队列中的时候Message会持有当前Handler引用,当Looper处理到当前消息的时候,会调用Handler#handleMessage(Message).
  3. 在java中,no-static的内部类会 隐式的 持有当前类的一个引用。static的类则没有。

在什么地方引起了内存的泄露呢?再看看下面一段代码

  1. public class SampleActivity extends Activity { 
  2.  
  3.  private final Handler mHandler = new Handler() { 
  4.  @Override 
  5.  public void handleMessage(Message msg) { 
  6.  // ... 
  7.  } 
  8.  } 
  9.  
  10.  @Override 
  11.  protected void onCreate(Bundle savedInstanceState) { 
  12.  super.onCreate(savedInstanceState); 
  13.  
  14.  // 发送一个10分钟后执行的一个消息 
  15.  mHandler.postDelayed(new Runnable() { 
  16.  @Override 
  17.  public void run() { } 
  18.  }, 600000); 
  19.  
  20.  // 结束当前的Activity 
  21.  finish(); 
  22.  } 

当Activity结束后,在 Message queue 处理这��Message之前,它会持续存活着。这个Message持有Handler的引用,而Handler有持有Activity(SampleActivity)的引用,这个Activity所有的资源,在这个消息处理之前都不能也不会被回收,所以发生了内存泄露。

解决办法,看下面一段代码

  1. public class SampleActivity extends Activity { 
  2.  
  3.  
  4.  private static class MyHandler extends Handler { 
  5.  private final WeakReference<SampleActivity> mActivity; 
  6.  
  7.  public MyHandler(SampleActivity activity) { 
  8.  mActivity = new WeakReference<SampleActivity>(activity); 
  9.  } 
  10.  
  11.  @Override 
  12.  public void handleMessage(Message msg) { 
  13.  SampleActivity activity = mActivity.get(); 
  14.  if (activity != null) { 
  15.  // ... 
  16.  } 
  17.  } 
  18.  } 
  19.  
  20.  private final MyHandler mHandler = new MyHandler(this); 
  21.  
  22.  
  23.  private static final Runnable sRunnable = new Runnable() { 
  24.  @Override 
  25.  public void run() { } 
  26.  }; 
  27.  
  28.  @Override 
  29.  protected void onCreate(Bundle savedInstanceState) { 
  30.  super.onCreate(savedInstanceState); 
  31.  
  32.  // 发送一个10分钟后执行的一个消息 
  33.  mHandler.postDelayed(sRunnable, 600000); 
  34.  
  35.  // 结束 
  36.  finish(); 
  37.  } 

ok,结束

NOTE: 好多人有担心弱引用的Activity回收的情况,这个完全不用担心的,因为我们在这个界面的时候,这个Activity 是不会被回收的,想想 如果我们的这个Activity被回收了,我们的这个界面是怎么存在的呢?

NOTE2: 各位,我是参照AsyncTask ,查看文档和自己的理解,存在我解释不了的地方,还望见谅,如有错误还望见谅。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论