1、概述
Looper的主要工作是维护一个消息队列,循环地执行以下操作:
(1)从队列中取出消息
(2)将消息交付给Handler处理
(3)回收该消息
Handler的主要工作便是发送消息以及处理消息:
(1)发送消息到消息队列中(入队操作)
(2)处理接收到的消息
Message就不用说了,封装了一些数据,而且还持有对Handler的引用。
2、Looper源码解析:
looper中主要的方法有两个,一个是prepare()方法,一个是loop()方法。
先看prepare()方法,这是Looper的外部入口方法:
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
首先看一下第二行的sThreadLocal,它是ThreadLocal类的实例。
public class ThreadLocal<T> {
//省略部分代码
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
}
可以看到set()方法其实就是将一个对象绑定到了当前线程上,类似的它的get方法则是取出保存的这个对象。
所以prepare方法主要的工作为:
(1)如果已经存在Looper对象,则抛出异常,告诉应用一个线程只能有一个Looper。
(2)如果不存在的话,新建一个Looper对象,然后绑定到当前线程上。
然后来看一下第6行中用到的Looper的构造方法:
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
这是一个私有的构造方法,主要创建了一个消息队列。
最后便是loop()方法了:
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
第2行,又声明了一个me的Looper对象,查看myLooper()方法:
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
发现me也就是之前在prepare()方法中创建并绑定到当前线程上的那个Looper()对象。
紧接着第6行,又拿到了looper对象中的消息队列(也就是构造方法中创建的那个)。
第13行到44行,便是概述中所说的looper的主要工作了,循环地进行下面操作:
(1)从队列中取出消息: 第三行queue.next()便是从消息队列中取出消息,可能会产生阻塞。
(2)将消息交付给Handler处理:第26行,msg.target就是概述中说的msg对handler的引用,所以此时本质上是handler对消息进行了处理。
(3)回收该消息:第43行对消息进行了回收。
至于代码中的ident相关,推荐阅读:android IPC通信中的UID和PID识别
3、Handler源码解析
首先看一下构造方法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 that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
2-9行是检测Handler是不是有可能导致内存泄露,并且官方推荐使用静态内部类来实现。
第11行再次调用了Looper.myLooper(),拿到了当前线程保存的looper对象,第16行拿到了该looper的messageQueue。
拿到了消息队列,handler自然就有了发送Message的能力,以下全都是sendMessage方法:
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what){
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
可以看到sendMessage最终都是调用了sendMessageAtTime()方法:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
sendMessageAtTime方法在判断了消息队列不为空后,又调用了enqueueMessage()方法。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
enqueueMessage方法最终调用了消息队列的入队方法,这样发出的消息终于到了消息队列中。
对了,还记得之前在Looper.loop()方法中,执行了
msg.target.dispatchMessage(msg);
其中的target就是在该方法的第2行进行赋值的,保存了当前handler。
最后一句调用了消息队列的入队方法,将消息发送到了消息队列中。
紧接着就是回调方法dispatchMessage()了,想一想就知道dispatchMessage方法中肯定会涉及到我们重写的handleMessage方法。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
果然在第10行执行了handleMessage(msg)方法,不过很明显执行它是有条件的,即msg.callback、 mCallback均为null。
(1)msg.callback其实是一个runnable对象,当我们在使用handler的post系列的方法时,需要传入一个Runnable对象:
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
sendMessageDelayed()方法之前写了,传入的是Message对象和延迟时间,所以getPostMessage(r)方法便是将Runnable对象封装成一个Message对象:
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
该方法的第3行,将runnable对象给了msg的callback属性。
该方法第2行Message.obtain(),源码中的注释解释得很好。如果Message池不为空的话,就取出一个message对象,并将它清空,否则的话创建一个新的Message对象:
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
扯了这么多,其实就是想说我们在使用sendMessage(Message msg)方法中,msg.callback默认是为null的。
(2)那么再来看看mCallback:
mCallBack是CallBack接口的实例,作为Handler类的成员变量,在构造参数中被初始化:
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;
}
而我们默认使用的是无参的构造方法时,mCallback默认也是为null的:
public Handler() {
this(null, false);
}
在dispatchMessage()方法msg.callback、 mCallback均为空时,便会执行handleMessage()方法了,与此同时,福利也来了,这是一个空方法~
/**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}
只有一行注释,子类必须重写这个方法来接收Message对象。
4、一个范例:
说了这么多,也该给一个范例,让身为静态内部类的Handler发出Message后,msg最后能回到自家的handleMessage()手里:
这是一个简单的按钮倒计时操作,点击后按钮开始倒计时60秒,时间到了后又恢复为之前的状态(当然这个功能也可以用CountDownTimer类来实现)。
布局就一个Button就不贴了,下面是Activity的代码:
public class HandlerActivity extends AppCompatActivity {
private MyHandler mHandler;
final private static int UPDATE = 1;
final private static int FINISH = 2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
Button btn = (Button) findViewById(R.id.btnHandler);
mHandler = new MyHandler(btn);
}
static class MyHandler extends Handler {
private WeakReference<Button> buttonWeakReference;
MyHandler(Button button) {
buttonWeakReference = new WeakReference<>(button);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE:
if (buttonWeakReference.get() != null)
buttonWeakReference.get().setText(String.valueOf(msg.arg1));
break;
case FINISH:
if (buttonWeakReference.get() != null){
buttonWeakReference.get().setClickable(true);
buttonWeakReference.get().setText("Button");
}
break;
default:
break;
}
}
}
public void onClick(View v) {
switch (v.getId()){
case R.id.btnHandler:
//设置Button不可点击
v.setClickable(false);
//启动新线程
new Thread() {
@Override
public void run() {
for (int i = 60; i > 0; i--) {
//发送消息【更新】
Message msg = new Message();
msg.what = UPDATE;
msg.arg1 = i;
mHandler.sendMessage(msg);
//休眠1s
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//发送消息【结束】
Message msg = new Message();
msg.what = FINISH;
mHandler.sendMessage(msg);
}
}.start();
break;
default:
break;
}
}
}
先写到这里吧。。。
待补充:
1、总结
2、send、post方法
3、messageQueue的实现