从Android Handler内部类到WeakReference的知识关联
Handler:
普通使用方法:
Handler用于处理和从队列MessageQueue中得到Message。一般我们要重写Handler的handleMessage(Message msg){}方法来处理,例如以下代码:
public class MainActivity extends Activity {
private TextView textView; Handler normalHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.i("test",textView.getText().toString());
break; default:
break;
}
};
};
}
问题:
这个时候Handler会被Android SDK中Lint工具检查警告你(左边那个黄色灯泡+叹号):This Handler class should be static or leaks might occur 。
原因:
This Handler class should be static:
(知识点一)为什么静态内部类能够解决问题呢?或者说静态内部类和非静态内部类的差别是什么?
举例:class A{int a; static int b class B{} static class C{} } (A是外部类,B非静态内部类,C静态内部类,a普通字段。b静态字段)
1)B非静态内部类:
能够訪问A.a和A.b,也就是外部的属性都能方位。
由于B隐式的持有A类对象的引用。相当于A的属性
2)C静态内部类:
C仅仅能够訪问A.b,不能够方位A.a。为什么?由于C不含有A的引用。它和A类是同一个级别。仅仅只是写到了A类的内部。
本例原因:
Handler匿名内部类,隐式的持有了外部类Activity的引用(这就是为什么你能在handleMessage()中调用MainActivity中TextView等的属性)。
--->而以后调
Message message = normalHandler.obtainMessage();
normalHandler.sendMessageAtTime(message , 100*1000);
得到的message中又含有这个Handler的引用(能够看源代码)。
在100秒后message被运行,这期间message被放在MessageQueue中,MessageQueue在Looper中,Looper是线程的本地变量。
也就是说MainActivity即使生命周期走完了也不会垃圾回收,为什么?由于Java的垃圾回收机制,就是看一个对象有没有被引用(从线程中的主要对象開始,对象之间的引用形成网状结构,假设有类的对象不在这张网上,就证明它没被引用。这就是数据结构中图的遍历,什么连通子图,非连通子图)。
而本文中一个MainActivity被Handler持有引用。Handler被Message持有引用,Message被MessageQueue持有引用,MessageQueue被Looper持有引用,Looper为线程本地变量,线程不被摧毁。它就不会被销毁。
所以即便用户已经切换、退出到别的Activity。MainActivity占有的内存仍旧不会被释放。
解决方式:
打破引用链:
1.Message在100秒后被处理。之后回收Message,然后回收MainActivity。
(所以是实际上,你仅仅要不发非常长时间的Message也不会有什么问题)
2.使Handler不持有MainActivity的引用,用弱引用WeakReference:(简单讲,就是仅仅有WeakReference引用的对象。垃圾回收将回收该对象,以后再另写一篇引用的文章吧)
正常代码:
MyHandler handler = new MyHandler(this); public static class MyHandler extends Handler {
private WeakReference<MainActivity> reference; public MyHandler(MainActivity activity) {
reference = new WeakReference<MainActivity>(activity);
} @Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.i("test",textView.getText().toString());
break; default:
break;
}
}
}
从Android Handler内部类到WeakReference的知识关联的更多相关文章
- Android内存Context泄露:Handler&内部类
1 public class SampleActivity extends Activity { 2 3 private final Handler mLeakyHandler = new Handl ...
- 【译】什么导致了Context泄露:Handler&内部类
思考下面代码 public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Hand ...
- 【Android】[转] Android Handler应设为static
android开发中,使用Lint检测时会提示这么一句话 : This Handler class should be static or leaks might occur.意为handler应用s ...
- Android Handler leak 分析及解决办法
In Android, Handler classes should be static or leaks might occur, Messages enqueued on the applicat ...
- Android Handler Leak
转自:Android中使用Handler引发的内存泄露 在Activity中,经常会用到自定义的Handler来处理主线程收到的Message,但是ADT20以后,直接定义的如下定义的内部会有提示说这 ...
- Android Handler 机制总结
写 Handler 原理的文章很多,就不重复写了,写不出啥新花样.这篇文章的主要是对 handler 原理的总结. 1.Android消息机制是什么? Android消息机制 主要指 Handler ...
- 85、android handler的警告Handler Class Should be Static or Leaks Occur
转载:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1106/1922.html 在使用Handler更新UI的时候,我是这样写 ...
- Android handler 详解(面试百分之100问到)
handler在Android中被称为“消息处理者”,在多线程中比较常用. handler内部实现原理 handler实现机制:1,Message对象,表示要传递的一个消息,内部使用链表数据结构实现一 ...
- Android handler 可能会造成内存泄露
Android handler 可能会造成内存泄露 Android Studio 使用 Handler 时: private Handler handler = new Handler(){ @Ove ...
随机推荐
- hdu4267 A Simple Problem with Integers
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (J ...
- hibernate jpa 2.0 报错Hibernate cannot unwrap interface java.sql.Connection
今天在做报表的时候,利用Hibernate JPA 2.0需要获取数据库连接com.sql.Connection的时候获取不到,网上说用这种方式解决: entityManager.getTransac ...
- Ubuntu14.04配置cuda-convnet
转载请注明:http://blog.csdn.net/stdcoutzyx/article/details/39722999 在上一个链接中,我配置了cuda,有强大的GPU,自然不能暴殄天物,让资源 ...
- 前端--关于javascript基础
首先javascript不是浏览器的附属品,只能说它大多数的运行环境是在浏览器中的,但又不仅仅局限于浏览器中.它是一门真正的程序设计语言,在这方面它和java.c.c++.c#是等同的,只不过它不直接 ...
- iPhone6设计自适应布局
http://www.devtalking.com/articles/adaptive-layout-for-iphone6-1/ http://www.devtalking.com/articles ...
- application windows are expected to have a root view controller错误
产生这个提示的操作:在xcode4.6中创建一个名字为appTest空工程,create一个ios-application-empty application,直接编译运行 错误提示:虽然编译通过,也 ...
- ios 获取屏幕的属性
屏幕尺寸 CGRect screen = [UIscreen mainScreen].bounds 状态栏尺寸 CGRect rect = [[UIApplication sharedApp ...
- EC读书笔记系列之1:条款1、条款2、条款3
条款1:视C++为一个语言联邦 记住: ★C++高效编程守则视状况而变化,这取决于你使用C++的哪一部分 C: Object-oriented c++: Template c++: STL 条款2:尽 ...
- li浮动引起ul高度坍陷的解决方法
我们都知道float在CSS中的作用是使元素脱离正常的文档流并使其移动到其父元素的“最左边”或“最右边”.元素浮动之后,它脱离当前正常的文档流,所以无法撑开其父元素,造成父元素的高度塌陷.如下的代码就 ...
- ruby更换为淘宝的源
我们在使用gem更新的时候,经常会为速度抓狂,其实gem默认的源是https://rubygems.org,比较慢众所周至的原因了. 可以将源更换到国内的taobao源 查看当前有的源 gem sou ...