一.Handler的两类使用方法
Handler里面有两类方法,一类是sendxxxx(),另一类是postxxxxx()
A. sendxxxx方法
1.sendEmptyMessage(int what):只发送了一个what值,也就是handleMessage收到的msg里面what的值
2.sendEmptyMessageDelayed(int what,long delayMillis): 指定延时多少毫秒后发送what
3.sendMessage(Message msg):立即发送信息,需要传入一个Message对象作为参数
4.sendMessageDelayed(Message msg, long delayMillis):延迟一定时间发送message对象
5.sendEmptyMessageAtTime(int what, long uptimeMillis):在一具体时间发送空消息
6.sendMessageAtTime(Message msg, long uptimeMillis):不说也知道了,在一具体时间发送message对象
7.sendMessageAtFrontOfQueue(Message msg):插入消息队列的头部,然后next就是它执行了
注:以上在handler源码里除了7 sendMessageAtFrontOfQueue 最终没有调用 sendMessageAtTime 方法外,其他方法最终都指向了 sendMessageAtTime方法
B.postXXX方法
1.post(Runnable r):Runable对象作为参数,post完之后,直接可以执行,Runable对象里面的run方法
2.postDelayed(Runnable r, long delayMillis):延迟一定时间执行runable对象
3.postAtTime(Runnable r, long uptimeMillis)在一具体时间执行runable对象
4.postAtFrontOfQueue(Runnable r):在消息队列头部插入runable对象执行
post方法执行举例
package practise.heima.com.customview;
import android.app.Activity;
import android.os.Handler;
import android.os.Bundle;
import android.widget.TextView;
public class HandlerActivity extends Activity {
private TextView tv;
Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mhandler);
tv= (TextView) findViewById(R.id.tv);
handler.postDelayed(new Runnable() {
@Override
public void run() {
tv.setText("Runable 对象执行");
}
},2000);//利用post方法,延迟两秒执行Runbale
}
}
二 send 和post方式有什么区别吗?
其实只是实现形式的不同,区别不大。不管是send或者post 最终的执行都是在 dispatchMessage(Message msg) 里面,源码如下:
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //如果message对象里面的callback不为空执行handleCallback(msg)
handleCallback(msg);
} else {//否则的话
//如果handler对象里的 mCallback不为空的话,就执行mCallback的handleMessage(msg)方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//mCallback为空的话,就执行Handler的handleMessage(msg)方法
handleMessage(msg);
}
}
可以发现,dispatchMessage做了两个if判断,也就是有三种执行方法。
A.post方法的执行
post方法对应的是msg.callback != null 的判断,这个是Message对象里面定义的callback属性,是个Runable对象,
Runnable callback;
其实去看Handler类里post方法源码可以发现post方法的Runnable对象参数,通过getPostMessage(Runnable r)生成了一个有Runnable类型属性的Message对象,并调用sendMessageDelayed 把这个包含Runnable对象的Message发出去了。
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
当dispatchMessage收到消息的时候判断message的callback是否为空,不为空,就用handleCallback(msg),执行了最开始传递进来的Runnable对象
private static void handleCallback(Message message) {
message.callback.run();
}
B.send方法的执行
send方法对应的是最后的Handler的handleMessage(msg) 的执行,这个执行的一般都是我们在定义handler时,重写的handleMessage(msg) 方法。Message的target属性是Handler类型,在让消息排队的时候执行enqueueMessage方法,在里面,handler对象本身让message对象给打包排队去了,并最终执行
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
C.mCallback 的执行
Handler定义了一个 Callback接口。通过看源码发现,dispatchMessage 里面的 mCallback 属性,都是通过构造函数赋值的,也就是说,在new handler对象的时候,就可以传递一个实现了Callback接口的对象进来,最终可以在dispatchMessage 里面执行这个实现Callback接口的对象的参数的handleMessage(msg)方法。
所以,使得Handler能够处理Message,我们有两种办法:
1. 向Hanlder的构造函数传入一个Handler.Callback对象,并实现Handler.Callback的handleMessage方法
2. 无需向Hanlder的构造函数传入Handler.Callback对象,但是需要重写Handler本身的handleMessage方法
也就是说无论哪种方式,我们都得通过某种方式实现handleMessage方法
还有一点,这种方法是可以带有返回值的,如果返回false,可以既执行mCallback的handleMessage(msg)方法,又可以执行重写的handler的handleMessage(msg)方法
使用Callback形式的handler
Handler handler=new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
}){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
Handler handler=new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Log.e("HandlerActivity","handler执行Callback()");
return false;//false 则handler本身重写的handleMessage会执行,true不会
}
}){
@Override
public void handleMessage(Message msg) {
Log.e("HandlerActivity","handler执行handleMessage()");
}
};
源码里有关mCallback的地方。
final Callback mCallback;
public interface Callback {
public boolean handleMessage(Message msg);
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}