您的位置:首页 > 移动开发 > Android开发

Android Hanlder综合

2016-03-01 21:49 344 查看
有些两三年工作经验的同学对于handler还处在滥用的状态,所以写这篇文章总结一下handler的几点。

首先强调,handler不是线程,很多初学者甚至有点经验的都把handler当成线程来看待,以为用上handler就开启线程操作了,这是不对的。还有一种用法是,用上handler就以为一定是在UI线程中操作了,也不太对。

那么Handler是什么?

Handler是一个事件操作的处理对象,在命令模式中是充当命令处理者的角色。它是一个任务的执行者,依附在线程中进行具体的任务处理。它是一个普通的Object对象,在指定的线程中执行它的handleMessage方法而已,跟线程其实并没有太多关系,只是任何方法都需要在线程中运行。

Hanlder不一定在UI线程中执行:

一般Handler都是用来做UI操作的,但并不代表用上Handler就表示一定可以进行UI操作。你可能在非Activity的类的方法中写了这样一句代码:

public void xxx(){
new Handler().post(new Runnable(){
public void run(){
textView.setText("abc");
}
}
);
}


如果你一不小心在工作线程中调用了xxx()方法,你的app可能会产生崩溃。这里有两个问题,一是创建的handler并无绑定的looper对象或者未开启loop()方法,报错如下:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()


二是该handler的创建是在工作线程中,即使looper对象是prepared且开启了loop循环,该处代码也会因为loop()方法(也即handler处理消息)不是执行在UI线程中却进行UI操作而报错。如果需要保证在UI线程中执行,handler的创建需在主线程中,或者主动传入主线程的looper对象:

new Hanlder(Looper.getMainLooper())


Hanlder使用场景

Handler常见用途有两种:

一是异步线程通知回调主线程事件;

二是发起延时的UI操作任务;

Handler为异步而生,但在一个成熟的app中,应当有独立的异步处理的工具类,这个工具类应是有线程池操作的,而不是随意的使用new thread + handler post方式来进行异步操作,无论从代码整洁性还是可能带来的其它性能问题方面考虑。

Handler的内存泄露问题

这个是android4.0开始,当你使用handler时adt会自动发出可能引起内存泄露的警告。原因是如果你使用handler发送了延迟的消息或者因其它原因导致的handleMessage执行开始之前,activity已经执行了finish()方法,这个时候会由于handler持有外部类activity的引用而导致acitivty无法被GC回收引起内存泄露。你需要在ondestroy()中调用下面这句代码:

mHandler.removeCallbacksAndMessages(null);


当然这句代码可能会忘记添加,所以我更推荐直接使用WeakHandler,它使用弱引用来规避了内存泄露的的问题:https://github.com/badoo/android-weak-handler

由Handler创建消息对象的正确方法

平时创建消息Message可能是直接new message()

官方提示:

the preferred way to get a Message is to call {@link #obtain() Message.obtain()


推荐使用

handler.obtainMessage()
or
Message.obtain()


Message类中使用了Recycle机制 ,它的obtain方法会复用仓库中暂时无用的message对象,避免重新创建新的对象而造成更多的性能消耗。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: