原博客地址:https://blog.csdn.net/weixin_40400031/article/details/96324854
使用Handler来解决通讯问题,是开发必备技能,但就是这家喻户晓的Handler,却偏偏最容易造成内存泄漏。
接下来我列出几种使用Handler的方式,以及各自的问题:
关于内存泄漏,请参考:Android 关于内存泄露,你必须了解的东西
关于JAVA引用类型,请参考:你真的懂 Java 的内存管理和引用类型吗?
第一种(公开静态handler):
写法:在Activiy中创建公开静态handler (public static Handler handler),并在onCreate()中实例化,以给其他类使用。
优点:这样创建handler,可以随意实现Activity与Activity/Service进行通讯,只要在需要的地方,使用目的Activity的handler调用sendMessage()即可。
缺点:必会造成内存泄漏 (因为static变量本身不持有Activity的引用,但是在onCreate()中实例化就给handler加上了对Activity的强引用。当Activity销毁的时候,由于handler的强引用,导致Activity无法被GC回收)
解决办法:无药可救,被static变量持有了强引用,那就完了
第二种(非静态handler):
写法:在Activity创建一个非静态匿名内部类对象handler (private Handler handler ) ,并在onCreate()中实例化
优点:相比于第一种,非静态handler不能被其他类随意使用,但依旧可以用于网络等耗时操作,用作结束时的通知(在调用耗时操作时将handler作为参数传递过去,之后等耗时操作结束,再使用该handler调用sendMessage()即可)。但是不会像第一种那样百分百造成内存泄漏。
缺点:1.只有Activity主动给予handler的地方才可以使用,无法实现Activity与Activity之间的通讯。
2.如果Activity销毁时,Handler有未处理或处理中的Message,则Message持有handler,handler持有Activity,导致Activity无法回收
解决办法:在Activity的onDestroy()中调用handler.removeCallbacksAndMessages()切断Handler与Activity之间的引用。
第三种(自定义Handler,内部对Activity进行弱引用)
写法:
//创建子类,采用弱引用:
public abstract class MyHandler extends Handler {
private Activity activity ;
private WeakReference<Activity> weakReference ;
public MyHandler(Activity activity) {
weakReference = new WeakReference<Activity>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(weakReference.get() == null){
return;
}else{
handle(msg); //处理message
}
}
public abstract void handle(Message msg);
}
//在Activit中创建实例
public class HandlerActivity extends BaseActivity {
public MyHandler handler ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
handler = new MyHandler(context){
@Override
public void handle(Message msg) {
//do something...
}
};
}
}
优点:由于使用了弱引用(WeakReference),所以Activity销毁时,即使Handler还有message要处理,Activity也依旧会被GC回收。其他功能同第二种。
缺点:没啥缺点,就是要单独写个子类
最后:大家不要搞这么蛋疼的Handler了,在通讯这块还是使用EventBus这类成熟框架吧!
如果嫌EventBus书写分类繁琐,可以参考小弟的框架EventBox
以上若有不对的,还望指教,谢谢