问题描写叙述

曾几何时,我们用原来的办法使用Handler时会有以下一段温馨的提示:

This Handler class should be static or leaks might occur

以下是更具体的说明(Android Studio上的警告,不知道Eclipse上是否同样)

Since this Handler is declared as an inner class, it may prevent the outer class from being garbage collected. If the Handler is using a Looper or MessageQueue for a thread other than the main thread, then there is no issue. If the Handler is using the Looper or MessageQueue of the main thread, you need to fix your Handler declaration, as follows: Declare the Handler as a static class; In the outer class, instantiate a WeakReference to the outer class and pass this object to your Handler when you instantiate the Handler; Make all references to members of the outer class using the WeakReference object.

大概意思就是:

一旦Handler被声明为内部类,那么可能导致它的外部类不可以被垃圾回收。假设Handler是在其它线程(我们通常成为worker thread)使用Looper或MessageQueue(消息队列)。而不是main线程(UI线程),那么就没有这个问题。

假设Handler使用Looper或MessageQueue在主线程(main thread),你须要对Handler的声明做例如以下改动:

声明Handler为static类。在外部类中实例化一个外部类的WeakReference(弱引用)而且在Handler初始化时传入这个对象给你的Handler;将全部引用的外部类成员使用WeakReference对象。

解决方式一

上面的描写叙述中基本上把推荐的改动方法明白表达了出来。以下的代码是我自己使用中的一个实现,请參考:

private CopyFileHandler mHandler;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_appstart);
mHandler = new CopyFileHandler(this);
startCopyDBThread();
} private void startCopyFileThread(){
Log.d(TAG, "startCopyDBThread");
new Thread(new Runnable() {
@Override
public void run() {
//DO SOMETHING LIKE: copyDBFile();
Message msg=mHandler.obtainMessage();
mHandler.sendMessage(msg);
}
}).start();
} private static class CopyFileHandler extends Handler {
WeakReference<AppStartActivity> mActivity;
public CopyFileHandler(AppStartActivity activity) {
mActivity = new WeakReference<>(activity);
} public void handleMessage(Message msg) {
final AppStartActivity activity = mActivity.get();
//handle you message here!
}
}

为什么会内存泄漏

那么为什么不这样做会引发内存泄漏呢?

这与几个关键词有关:内部类、Handler的消息循环(Looper)、Java垃圾回收机制。

须要强调一下,并非每次使用Handler都会引发内存泄漏。这里面有一定的几率,须要满足特定条件才会引起泄漏。

内部类会有一个指向外部类的引用。

垃圾回收机制中约定。当内存中的一个对象的引用计数为0时。将会被回收。

Handler作为Android上的异步消息处理机制(好吧,我大多用来进行worker thread与UI线程同步),它的工作是须要Looper和MessageQueue配合的。简单的说,要维护一个循环体(Looper)处理消息队列(MessageQueue)。

每循环一次就从MessageQueue中取出一个Message。然后回调对应的消息处理函数。

假设,我是说假设,循环体中有消息未处理(Message排队中),那么Handler会一直存在。那么Handler的外部类(一般是Activity)的引用计数一直不会是0,所以那个外部类就不能被垃圾回收。

非常多人会遇到activity的onDestroy方法一直不运行就是这个原因。

还有一个解决方式的尝试

警告描写叙述中提到了Handler在worker thread中使用Looper或MessageQueue,我尝试了一下。请大家品鉴。

    private Handler testHandler;
private Thread mThread = new Thread() {
public void run() {
Log.d(TAG,"mThread run");
Looper.prepare();
testHandler = new Handler() {
public void handleMessage(Message msg) {
Log.d("TAG", "worker thread:"+Thread.currentThread().getName());
switch (msg.what) {
//handle message here
}
}
};
Looper.loop();
}
}; //start thread here
if(Thread.State.NEW == mThread.getState()) {
Log.d(TAG, "mThread name: " + mThread.getName());
mThread.start();
} //send message here
testHandler.sendEmptyMessage(1);

參考:

http://stackoverflow.com/questions/11407943/this-handler-class-should-be-static-or-leaks-might-occur-incominghandler

http://m.blog.csdn.net/blog/wurensen/41907663

http://blog.csdn.net/lmj623565791/article/details/38377229

Android实战技巧之三十八:Handler使用中可能引发的内存泄漏的更多相关文章

  1. Handler使用中可能引发的内存泄漏

    https://my.oschina.net/rengwuxian/blog/181449 http://www.jianshu.com/p/cb9b4b71a820 http://blog.csdn ...

  2. 【转】Android实战技巧之四十九:Usb通信之USB Host

    零 USB背景知识 USB是一种数据通信方式,也是一种数据总线,而且是最复杂的总线之一. 硬件上,它是用插头连接.一边是公头(plug),一边是母头(receptacle).例如,PC上的插座就是母头 ...

  3. Android实战技巧之十二:Android Studio导入第三方类库、jar包和so库

    第三方类库源码 将一网友的XMPP代码从ADT转到AS时,发现其使用了第三方类库,源码放在了lib下,直接在AS中Import project,第三方类库并没有自动导入进来,看来需要自己动手了. 项目 ...

  4. Android实战技巧之十九:android studio导出jar包(Module)并获得手机信息

    AS中并没有独立的Module 工程,可是能够在普通的Project中增加Module.所谓的Module就是我们通常所指的模块化的一个单元.并经常以jar包的形式存在.以下以一个获取手机信息的样例演 ...

  5. Android学习指南之三十八:Android手势操作编程[转]

    手势操作在我们使用智能设备的过程中奉献了不一样的体验.Android开发中必然会进行手势操作方面的编程.那么它的原理是怎样的呢?我们如何进行手势操作编程呢? 手势操作原理 首先,在Android系统中 ...

  6. Android实战技巧之三十七:图片的Base64编解码

    通经常使用Base64这样的编解码方式将二进制数据转换成可见的字符串格式,就是我们常说的大串.10块钱一串的那种,^_^. Android的android.util包下直接提供了一个功能十分完备的Ba ...

  7. (转载)Android项目实战(二十八):Zxing二维码实现及优化

    Android项目实战(二十八):Zxing二维码实现及优化   前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中 ...

  8. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21我要评论 这篇文章主要介绍了Android项目 ...

  9. Android实战技巧:深入解析AsyncTask

    AsyncTask的介绍及基本使用方法 关于AsyncTask的介绍和基本使用方法可以参考官方文档和Android实战技巧:多线程AsyncTask这里就不重复. AsyncTask引发的一个问题 上 ...

随机推荐

  1. 查看Linux系统资源占用

    Linux查看进程占用磁盘IO yum install -y itop iotop -oP Linux查看进程网络使用 yum install -y nethogs nethogs nethogs e ...

  2. 发现一个FreeSWITCH bug

    在研究FreeSWITCH视频会议的混屏问题时候发现一个bug. 已提交jira. 附上代码,问题很明显,不解释 =========================================== ...

  3. 【BZOJ 2186】 2186: [Sdoi2008]沙拉公主的困惑 (欧拉筛,线性求逆元)

    2186: [Sdoi2008]沙拉公主的困惑 Description 大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞 ...

  4. codevs1033 蚯蚓的游戏问题 裸最小费用最大流,注意要拆点

    因为蚯蚓走过的路径不能重合,所以把每个点拆成两个点,容量赋为1,保证不会走过相同的点,再加超级源点(程序中为1)和一个辅助点(程序中为2)容量赋为k来控制蚯蚓的数量,最后汇集到一个超级汇点上.做一遍最 ...

  5. 【序列莫队+树状数组】BZOJ3289-Mato的文件管理

    [题目大意] 一共有n份,每份有一个大小和一个编号.Mato每天随机选一个区间[l,r],拷贝出来(即对原序列不影响),给它们排序,并且每次只能交换相邻两份文件.问每天最少交换几次? [思路] 显然, ...

  6. bzoj 3900: 交换茸角

    3900: 交换茸角 Description 动物园里有 n 头麋鹿.每头麋鹿有两支茸角,每支茸角有一个重量.然而,一旦某头麋鹿上 两支茸角的重量之差过大,这头麋鹿就会失去平衡摔倒.为了不然这种悲剧发 ...

  7. [BZOJ5046]分糖果游戏

    题目大意: 有a,b两个人分糖,每个人都有一个能量值. 每个人每一轮可以选择进行两种操作: 1.取走最左边的糖果,补充相应的能量值并获取相应的美味度. 2.跳过这一轮,能量值-1. 问在每个人都采取最 ...

  8. [bzoj1006](HNOI2008)神奇的国度(弦图最小染色)【太难不会】

    Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则. 他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关 ...

  9. codevs 1962 马棚问题--序列型DP

    1962 马棚问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 每天,小明和他的马外出,然后他们一边跑一边玩耍.当他们结束 ...

  10. Fatal error: Call to undefined function mb_detect_encoding()

    1.找到php扩展目录(我的php扩展目录的路径是:C:\Program Files\AppServ\php\extensions)     在extensions目录下面找到php_mbstring ...