一般我都写handler的时候是这样的:

 
public class MyActivity extends Activity{
private final Handler myHandler = new Handler(){
public void handleMessage(Message msg){
//。。。。
} };
}

  

 
但是这样会引起内存泄露。。。 为什么会呢?
 
1. Android 启动时会自动创建主线程使用的Looper实例,Looper的主要工作是一个一个的处理队列中消息的。在android中,所有的android框架事件(eg:activity生命周期方法和点击事件方法)都是放到消息中,然后加入Looper要处理的消息队列中,由Looper负责一条一条的处理,Loope的生命周期和应用程序一样长.
2. 当一个handler在主线程初始化后,我们发送一个target为handler的消息到Looper处理的消息队列中,是个消息是包含了一个Handler的实例引用的,只有包含了一个实例引用才可以再消息中调用Handler#handlerMessage(Meaasge msg)完成消息的正确处理。
3、在Java中非静态的内部类和匿名内部类都会隐式的持有外部类的引用静态的内部类不会持有外部类的应用。
 
上面方法:Loopr ->myHandler->MyActivity ->持有各种资源
 
我们假设myHandler是一个延迟处理的比如下面:
 
public class MyActivity extends Activity{
private final Handler myHandler =newHandler(){
@Override
public void handleMessage(Messagemsg){
// ...
}
}
@Override
protected void onCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);// 发送一个延迟十分钟的消息
mLeakyHandler.postDelayed(newRunnable(){@Overridepublicvoidrun(){/* ... */}},1000*60*10);
// 然后结束当前页面
finish();
}
}

  

我们执行了Activity的finish方法,被延迟的消息会在被处理之前存在于主线程消息队列中10分钟,而这个消息中又包含了Handler的引用,而Handler是一个匿名内部类的实例,其持有外面的MyActivity 的引用,所以这导致了MyActivity 无法回收,进行导致MyActivity 持有的很多资源都无法回收,这就是我们常说的内存泄露。
如何解决呢???
思路就是避免使用非静态内部类。
继承Handler时
  1.放在单独的类文件中。。
  2.使用静态内部类。 因为静态内部类不会持有外部类的引用,就不会导致外部类实例的内存泄露。
当你需要在静态内部类中调用外部的Activity时,我们可以使用弱引用来处理。另外关于同样也需要将Runnable设置为静态的成员属性。
public class
MyActivity
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(SampleActivityactivity){
mActivity=newWeakReference<SampleActivity>(activity);
}
@Override public void handleMessage(Messagemsg){
SampleActivityactivity=mActivity.get();
if(activity!=null){
// ...}
}
}
private final MyHandler mHandler=newMyHandler(this);
/**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnables Runnable=newRunnable(){
@Override
public void run(){
/* ... */
}
};
@Override
protected void onCreate(BundlesavedInstanceState){
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中使用了非静态内部类导致的,就像本文提到的一样,所以当我们使用时要非静态内部类时要
格外注意,如果其实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。个人倾向于使用文章的静态类和弱引用的方法解决这种问题。

Handler引起的内存泄露的更多相关文章

  1. Android handler 可能会造成内存泄露

    Android handler 可能会造成内存泄露 Android Studio 使用 Handler 时: private Handler handler = new Handler(){ @Ove ...

  2. Android 中 Handler 引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.其实这可能导致内存泄露,代码中哪里可能导致内存泄露,又是如何导致内存泄露的呢?那我们就慢慢分析一下.http://w ...

  3. 【转】内部Handler类引起内存泄露

    如果您在Activity中定义了一个内部Handler类,如下代码: public class MainActivity extends Activity {       private  Handl ...

  4. Handler 引起的内存泄露

    先看一组简单的代码 1 2 3 4 5 6 7 8 9 public class SampleActivity extends Activity { private final Handler mHa ...

  5. Android 从java字节码告诉你 为什么Handler会造成内存泄露

    很多人面试的时候,都知道Handler 极易造成内存泄露,但是有一些讲不出来为什么,好一点的 会告诉你looper msg 之类的,但是你再往下问 为什么msg持有handler handler为什么 ...

  6. Android中Handler引起的内存泄露

    在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. 1 2 3 4 5 6 7 8 9 public class SampleActivit ...

  7. Android中Handler导致的内存泄露

    http://www.androiddesignpatterns.com/2013/01/inner-class-handler-memory-leak.html Consider the follo ...

  8. Android性能优化——之防止内存泄露

    又是好久没有写博客了,一直都比较忙,最近终于有时间沉淀和整理一下最近学到和解决的一些问题. 最近进行技术支持的时候,遇到了几个崩溃的问题,都是OOM异常,一般OOM异常给人的感觉应该是加载大图片造成的 ...

  9. Android之内存泄露、内存溢出、内存抖动分析

      内存   JAVA是在JVM所虚拟出的内存环境中运行的,内存分为三个区:堆.栈和方法区.栈(stack):是简单的数据结构,程序运行时系统自动分配,使用完毕后自动释放.优点:速度快.堆(heap) ...

随机推荐

  1. String bulit-in function

    tip: 和tuple一样,字符串也是不可变的类型,字符串的内建函数有非常多,我们一一举例来看看他们的作用 下面是用dir(str) 输出的内容: ['__add__', '__class__', ' ...

  2. Pyhton:List build-in function

    列表是Python中的可迭代对象之一,在讲列表的内建函数之前我们可以自己在IDE上看看都有那些内建函数,我们可以在pycharm中使用代码及其运行结果如下: print(dir(list)) ['__ ...

  3. 每次rand出来都是41?说好的随机数呢?!

    rand()函数是C++标准函数库提供的随机数生成器,生成0-RAND_MAX之间的一个"伪随机"整数,理论上可以产生的最大数值为2^16-1,即32767. rand()函数不接 ...

  4. SPOJ:Decreasing Number of Visible Box(不错的,背包?贪心?)

    Shadowman loves to collect box but his roommates woogieman and itman don't like box and so shadowman ...

  5. 枚举子集 Codeforces306 Div2 B

    题目 分析:用二进制法去枚举子集,同时判断满足条件的子集个数加1 #include "iostream" #include "cstdio" using nam ...

  6. Servlet分页查询

    分页查询: 1.逻辑分页查询:用户第一次访问时就把全部数据访问出来,添加到一个大集合中,然后放到session中,进行转发.通过页码等的计算,把要显示的内容添加到一个小集合中,转发.遍历小集合以显示当 ...

  7. spring+mybatis 多数据源整合--temp

    <!-- 数据源配置 -->   <bean id="ds1" class="org.apache.commons.dbcp.BasicDataSour ...

  8. mfc实现对话框全屏置顶显示

    一.MFC让对话框窗口始终在最前 方法一:在对话框的属性中,把SystemModal设置为True. 二.全屏显示 在CDialog7::OnInitDialog()中加入: 先取得分辨率, int ...

  9. 任务46:Identity MVC:登录逻辑实现

    任务46:Identity MVC:登录逻辑实现 实现登陆的方法 退出方法 _layout里面增加如下的代码: Login.cshtml 运行代码测试: 这个地方的单词之前拼错了.这里进行修正 输入账 ...

  10. KDotAlert

    一个iPhone X的适配让楼主受尽了自定义的苦,使用系统API多好,所以在楼主不懈的努力下,终于和组长达成一致:逐步用系统控件替换代码里面的自定义控件,第一个挨刀的就是 BlockAlertsAnd ...