Android学习-Handler内存泄漏

来源:互联网 发布:名器大魔王推荐知乎 编辑:程序博客网 时间:2024/06/02 01:59

2016/08/20

最近轻微强迫症又犯了,看着编译器上的那些带有黄色感叹号警告就十分难受,于是就下定决心清除我能看到的所有黄色感叹号,一般我不会用像图1中系统提示那些处理方法,


我觉得那是在欺骗自己,可能在处理这些警告上有些费时,但是不管怎样,自己开心就好,得意.前几天在写一个线程实例的时候

用到了Handler 来传递数据,我之前都是像图2那样写的,图2上已然出现了一个傲娇的黄色感叹号,警告的内容是 This Handler class should be static or leaks might occur (com.example.ndktest.MainActivity.1) 我把我那蹩脚英语能力和有道词典有机统一的结合之后,笼统的明白的这句话的意思是:这个Handler 类应该是静态的,否则可能引起内存泄漏问题,在我颇有成就感的品味被我翻译出来的译文的同时,我又开始蒙圈了,到底是什么原因出现这样奇葩的警告呢,我之前都是这么写的,从来都没有出现过内存泄漏的现象,那这个发生内存泄漏的概率岂不是很低,知其然而不知其所以然,苦恼数微秒之后,我就打开了浏览器,开始刨根问底,许久之后有了些收货.先附上我的测试代码

public class MainActivity extends Activity {public TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView) findViewById(R.id.tv);}Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {tv.setText("我收到了message");};};}


根据代码可以看出 handler 是一个内部类,内部类分两种,一种是普通内部类,也就是像上面代码里handler这个类那样,另一种是加static关键字的静态内部类,就是那段警告所说的改正后的类的类型.普通内部类隐含保存了外部类的引用,静态内部类就不是这样了,静态内部类只能访问外部类的静态成员.那这跟内存泄漏有什么关系呢,其实思考到这里,答案就已经很明朗了,关键点就在于普通内部类隐含保存了外部类的引用,如果我在上面代码的oncreate函数里添加finish()方法之后,在运行到finish()后,本应该进行对MainActivity 垃圾回收的,但是由于handler内部类有对MainActivity  的引用,所以是MainActivity 对象是不会被回收的,这就造成了内存的泄漏.要解决这样的问题,就要用到弱引用,在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,就会回收它的内存,不会考虑内存的充足与否。这样就解决了内存泄漏问题

改后的代码

public class MainActivity extends Activity {public TextView tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv = (TextView) findViewById(R.id.tv);}// Handler handler = new Handler() {//// public void handleMessage(android.os.Message msg) {//// tv.setText("我收到了message");//// };// };MyHandler handler = new MyHandler(this);static class MyHandler extends Handler {WeakReference<MainActivity> mActivity;public MyHandler(MainActivity activity) {mActivity = new WeakReference<MainActivity>(activity);}@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubsuper.handleMessage(msg);MainActivity a = mActivity.get();if (a != null) {a.tv.setText("我收到了message");}}}}





0 0