Handler可能导致的内存泄漏及其优化

package cc.cc;

import java.lang.ref.WeakReference;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
/**
 * Demo描述:
 * Handler可能导致的内存泄露及其优化
 *
 * 1 关于常见的Handler的用法但是可能导致内存泄露
 *   请参考方法initHandler()
 * 2 优化方式请参考BetterHandler和BetterRunnable的实现
 *
 * 关于Handler可以参考我以前写的:
 * http://blog.csdn.net/lfdfhl/article/details/40016165
 *
 * 参考资料:
 * 1 http://blog.csdn.net/krislight/article/details/9391403
 * 2 http://blog.csdn.net/myarrow/article/details/14223493
 * 3 http://2dxgujun.com/post/2014/09/11/Handler-Leaks-Solution.html
 * 4 http://blog.csdn.net/FeeLang/article/details/39059705
 *   Thank you very much
 *
 */
public class MainActivity extends Activity {
	private Handler mHandler;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	/**
	 * 常见的Handler的用法但是可能导致内存泄露
	 *
	 * 比如在旋转屏幕时该Activity重新绘制.
	 * 但是因为mHandler发送了一个延迟消息,所以消息队列持有mHandler对象
	 * 又由于new Runnable(){}持有外部类MainActivity的引用
	 * 所以Activity所占内存并不能向期望的那样被回收,这样就可能会造成内存泄漏.
	 *
	 * 这个例子中Handler的延迟时间比较久有20S,有点极端了,一般不会这么干;
	 * 这里只是为了更好地说明这个问题就这么写代码了。
	 *
	 */
	private void initHandler() {
		mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
			}
		};

		// ......doing something
		// ......doing something
		// ......doing something

		// 发送延迟消息
		mHandler.postDelayed(new Runnable() {
			@Override
			public void run() {

			}
		}, 1000 * 20);
	}

	/**
	 * 以下为优化方式
	 * 1 在此处把BetterHandler和BetterRunnable都设计为静态类,
	 *  这样它们就不会持有外部类的引用了.
	 * 2 在BetterHandler中利用WeakReference持有Activity.
	 *  常听说:"如果一个对象具有弱引用,那么当GC线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存"
	 *  其实准备地说应该是"如果一个对象只具有弱引用.........",即仅有弱引用而不存在对其的强引用才会将其回收.
	 *  那么此处对Activity采用了弱引用,会不会导致该Activity被回收呢?
	 *  答案是否定的。因为此处的Activity还在显示界面,当然存在其他对象对它的强引用。所以不会对其回收。
	 *
	 * 经过这样的优化,当旋转屏幕时需要销毁原Activity时;消息队列持有Handler对象.但此时Handler对象不再持有Activity的引用.
	 * 所以系统会回收该Activity所占内存.所以在handleMessage()中处理消息时需要判断Activity是否为空.
	 * 比如此处20秒后才处理消息 这个时候Activity为空.
	 */
	private static class BetterHandler extends Handler{
		private final WeakReference<Activity> activityWeakReference;
		public BetterHandler(Activity activity){
			activityWeakReference=new WeakReference<Activity>(activity);
		}
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if (activityWeakReference.get()!=null) {
				//.....handle message
			} else {
				System.out.println("Activity==null");
			}
		}
	}

	//同样采用静态内部类
	private static class BetterRunnable implements Runnable{
		@Override
		public void run() {
			// ......doing something
		}

	}

	//发送延迟消息
	private void sendMessage(){
		BetterHandler betterHandler=new BetterHandler(MainActivity.this);
		betterHandler.postDelayed(new BetterRunnable(), 1000 * 20);
	}

}

时间: 2024-08-07 16:59:14

Handler可能导致的内存泄漏及其优化的相关文章

非静态内部类可能导致的内存泄漏及其优化

package cc.cc; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 非静态内部类可能导致的内存泄露及其优化 * * 在MainActivity中定义了两个内部类InnerClassTest和ThreadSubClass. * 在这里需要注意一个问题: * 内部类持有外部类的引用!!!! * 或者说内部类对外部类持有隐式的引用!!!! * * 假如我们在内部类中做耗时的操作或者说有个while(

View的post方法导致的内存泄漏分析

简述: 写这篇文章的缘由是最近项目中查内存泄漏时,发现最终原因是由于异步线程调用View的的post方法导致的. 为何我会使用异步线程调用View的post方法,是因为项目中需要用到很多复杂的自定义布局,需要提前解析进入内存,防止在主线程解析导致卡顿,具体的实现方法是在Application启动的时候,使用异步线程解析这些布局,等需要使用的时候直接从内存中拿来用. 造成内存泄漏的原因,需要先分析View的post方法执行流程,也就是文章前半部分的内容 文章内容: View#post方法作用以及实

static关键字所导致的内存泄漏问题

大家都知道内存泄漏和内存溢出是不一样的,内存泄漏所导致的越来越多的内存得不到回收的失手,最终就有可能导致内存溢出,下面说一下使用staitc属性所导致的内存泄漏的问题. 在dalvik虚拟机中,static变量所指向的内存引用,如果不把它设置为null,GC是永远不会回收这个对象的,所以就有了以下情况: [java] view plain copy public class SecondActivity extends Activity{ private Handler mHandler = n

使用HandyJSON导致的内存泄漏问题相关解决方法

在移动开发中,与服务器打交道是不可避免的,从服务器拿到的接口数据最终都会被我们解析成模型,现在比较常见的数据传输格式是json格式,对json格式的解析可以使用原生的解析方式,也可以使用第三方的,我们的项目中使用的是阿里开源的一个swift编写的解析框架--HandyJSON. 在使用过程中,使用instruments的Leak Checks工具对内存泄漏进行检测时发现了这个框架导致了不少的内存泄漏,如图1-1: 这张图是在APP进入首页并将数据加载完毕时截取的,可以看到,HandyJSON一共

Android Weak Handler:可以避免内存泄漏的Handler库

这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! android使用java作为其开发环境.java的跨平台和垃圾回收机制已经帮助我们解决了底层的一些问题.但是尽管有了垃圾回收机制,在开发android的时候仍然时不时的遇到out of memory的问题,这个时候我们不禁要问,垃圾回收机器去哪儿了? 我们主要讲的是handler引起的泄漏,并给出三种解决办法,其中最后一种方

Android实战技巧之三十八:Handler使用中可能引发的内存泄漏

问题描写叙述 曾几何时,我们用原来的办法使用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 coll

在Activity中使用Thread导致的内存泄漏

原文链接 : Activitys, Threads, & Memory Leaks 原文作者 : AlexLockwood 译文出自 : 开发技术前线 www.devtf.cn 译者 : chaossss 校对者: yinna317 状态 : 完成 注:这篇博文涉及的源码可以在 GitHub 上面下载哦 做 Android 开发最常遇到的问题就是在 Activity 的生命周期中协调耗时任务,避免执行任务导致不易察觉的内存泄漏.不妨先读一读下面的代码,代码写了一个简单的 Activity,Act

常见的八种导致 APP 内存泄漏的问题(下)

百度搜索:小强测试品牌 QQ群:138269539 Handlers 同 样的,定义一个匿名的 Runnable 对象并将其提交到 Handler 上也可能导致 activity 泄漏.Runnable 对象间接地引用了定义它的activity 对象,而它会被提交到 Handler 的 MessageQueue 中,如果它在 activity 销毁时还没有被处理,那就会导致 activity 泄漏了. Threads 同样的,使用 Thread 和 TimerTask 也可能导致 activit

android中handler使用应该注意的问题(解决由handler引起的OOM内存泄漏)

最近,在项目过程中频繁的使用handler处理一些ui线程上的操作,以及使用handler的postdealy.然而使用过后却不对handler进行处理,进而产生了内存溢出现象,通过google,发现了解决这一问题的方法.下面贴出项目中的相关代码 /**********************************以下代码解决了handler有可能造成的内存泄漏***************************************************/ /** * 创建静态内部类