在 android中,Handler是非常重要且常用的对象。往往用来处理异步回调。很多系统实现都使用到了Handler。比如AsyncTask,IntentService,HandlerThread 等。
先给出一个简单是使用示例:
// Handler 使用示例 ###
// MyActivity.java
private Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
// super.handleMessage(msg);
Log.d(TAG, "handlerMessage==" + msg.what);
}
@Override
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
Log.d(TAG, "dispatchMessage==" + msg.what);
Log.d(TAG, "dispatchMessage==handler ### " + msg.getTarget());
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_self);
findViewById(R.id.button_click)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.v(TAG, "click this button...");
Message obtain = Message.obtain();
obtain.obj = new Date();
obtain.what = 12;
mainHandler.sendMessage(obtain);
}
});
}
(一般是在子线程中处理完成耗时操作之后,)将结果发送到主线程,此时往往会调用Handler#sendMessage(msg);方法。
说到Handler,往往跟 Looper与Message 一起来说,因为他们确实是密不可分的。
在使用Handler的使用
首先,通过Handler的构造方法创建Handler对象,并获取当前线程的Looper对象,以及Looper中的MessageQueue对象。
// Handler 的无参构造,实际上调用的是该构造方法
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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
这里将Handler与Looper 对象关联了。mLooper = Looper.myLooper(); 很简单,就是这样一句代码就完成了。
根据 android: Looper 源码浅析 [Handler,Looper,Message,MessageQueue] 这里的分析可知:
// Looper.java
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
是通过ThreadLocal#get()去获取的。
通过以上分析可知。创建Handler的时候,同时获取到了对应的Looper对象。
这里也可以看出ThreadLocal的威力。不需要你去专门指定key,只要是在当前线程,那么get()到的,就是之前你ThreadLocal#set()进去的对象。
设置进去,是在Looper#prepare()的使用。
handler.sendMessage()在Handler内部,真正调用的是Handler#enqueueMessage()方法。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; // --> 绑定 message 与 handler ###
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
该方法很重要,将Message与Handler对象关联起来了。
对于Handler,只要关注其构造方法,以及两个重要的方法sendMessage(),dispatchMessage()即可。
【粗粒度】整体看一下调用流程。首先,通过调用Handler#sendMessage()发送对应的Message对象;然后Looper.loop()方法中会拿到这个Message对象,并调用msg.target.dispatchMessage()方法,让Handler#dispacthMessage(msg)被调用。这样就可以通过重写Handler#dispatchMessage(msg)或者Handler#handlerMessage(msg)方法来拿到之前通过Handler#sendMessage(msg)发出的Message对象了。
- 问题1:为什么在主线程创建的
Handler不需要调用Looper.prepare()以及Looper.loop()方法?
答案很明确,系统已经帮忙创建了。(在ActivityThread里面。)
本文围绕Android中重要且常用的对象展开,介绍了其处理异步回调的用途及相关系统实现。给出使用示例,阐述了Handler、Looper、Message、MessageQueue的关联及创建过程,分析了调用流程,并解答了主线程创建Handler无需调用特定方法的问题。
3311

被折叠的 条评论
为什么被折叠?



