一般我都写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. YTU 1068: 复制字符串

    1068: 复制字符串 时间限制: 1 Sec  内存限制: 128 MB 提交: 602  解决: 382 题目描述 有一字符串,包含n个字符.写一函数,将此字符串中从第m个字符开始的全部字符复制成 ...

  2. Web Assembly背景

    Javascript ,也叫Ecma script,  是这家伙用了 10 天时间赶出来的.. 所以,各位程序猿们,如果你觉得老板 10 天要你们上线一个 App 是一个丧心病狂的事情,那么可以多想想 ...

  3. topcoder 的一些输入输出格式

    自从上年的11月份参加过TC的比赛后,就再也没有参加了,因为它的输入输出格式比较难接受,还有它的页面字体比较小,看得我很辛苦...藉口藉口--懒而已!不过以后我会尽量去参加的,为了提高自己的编程能力. ...

  4. ubuntu中使用apt-get安装zbar

    apt-get是linux中常用的shell命令,适用于deb包管理式的操作系统,主要用于自动从互联网的软件仓库中搜索.安装.升级.卸载软件或操作系统.apt-get命令一般需要root权限执行,所以 ...

  5. NOI前总结:点分治

    点分治: 点分治的题目基本一样,都是路径计数. 其复杂度的保证是依靠 $O(n)$ 找重心的,每一次至少将问题规模减小为原先的$1/2$. 找重心我喜欢$BFS$防止爆栈. int Root(int ...

  6. Two

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission( ...

  7. C++开发工程师面试题库 200~250道

    199  MFC中SendMessage和PostMessage的区别?答:PostMessage 和SendMessage的区别主要在于是否等待应用程序做出消息处理.PostMessage只是把消息 ...

  8. poj3249【拓扑排序】

    //题意:   给出一个有向无环图,每个顶点都有一个权值. //         求一条从入度为0的顶点到出度为0的顶点的一条路径, //         路径上所有顶点权值和最大. //我觉得只要明 ...

  9. bzoj 4316: 小C的独立集【仙人掌dp】

    参考:https://www.cnblogs.com/clrs97/p/7518696.html 其实和圆方树没什么关系 设f[i][j][k]为i点选/不选,这个环的底选不选 这个底的定义是设u为这 ...

  10. LuoguP2822 组合数问题(组合数,二维前缀和)

    P2822 组合数问题 输入输出样例 输入样例#1: 复制 1 2 3 3 输出样例#1: 复制 1 输入样例#2: 复制 2 5 4 5 6 7 输出样例#2: 复制 0 7 说明 [样例1说明] ...