Android学习-Handler内存泄漏

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;

	@Override
	protected 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;

	@Override
	protected 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);
		}

		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			MainActivity a = mActivity.get();

			if (a != null) {
				a.tv.setText("我收到了message");
			}

		}

	}

}





posted on 2016-08-20 16:46  记住我叫王凯  阅读(236)  评论(0编辑  收藏  举报

导航