我们平常在使用Handler的时候 是这样使用的
public class MainActivity extends AppCompatActivity {
TextView mTextView;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mTextView.setText((String) msg.obj);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.tv);
new Thread(new Runnable() {
@Override
public void run() {
Message msg = Message.obtain();
msg.obj = "更新UI";
mHandler.sendMessage(msg);
}
}).start();
}
}
1、我们来看一下new Handler()方法,我们来到Handler类中:
public Handler() {
this(null, false);
}
public Handler(Callback callback, boolean async) {
// 获取一个Looper对象
mLooper = Looper.myLooper();
// 如果mLooper为空,则抛出一个not called Looper.prepare()异常,
// 这就是我们在子线程中没有调用Looper.prepare()而直接new Handler时经常报出的错误
// 问题1:为什么我们在主线程中能直接new Handler而没有报错呢?
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、我们先来看一下 mHandler.sendMessage(msg); 方法,我们来到Handler类中:
public final boolean sendMessage(Message msg) {
// 调用延时为0的方法
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
// 如果设置的delay时间为负数,则重置时间为0
if (delayMillis < 0) {
delayMillis = 0;
}
// delay时间再加上系统时间
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
// 获取消息队列 MessageQueue,
// 问题2:这里的消息队列 mQueue 是在哪里赋值的?
MessageQueue queue = mQueue;
// ...
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 将msg.target设置为this,this即为 Handler
msg.target = this;
// 调用MessageQueue的enqueueMessage方法
return queue.enqueueMessage(msg, uptimeMillis);
}
3、我们来到 MessageQueue 类中:
boolean enqueueMessage(Message msg, long when) {
// ...
synchronized (this) {
// ...
// 将传进来的delay时间设置到 msg.when 中
msg.when = when;
// 创建一个临时对象来存放上次的消息mMessages
Message p = mMessages;
// 上个消息mMessages == null
// 或 传进来的delay时间为0
// 或 传进来的delay时间比上次的消息mMessages的delay时间小
if (p == null || when == 0 || when < p.when) {
// 将传进来的msg消息的next设置为上一条消息msg
msg.next = p;
// 当前消息mMessages置为传进来的msg
mMessages = msg;
} else {
// 创建一个临时对象,存放上一条消息msg
Message prev;
// 开一个死循环,不断读取队列并将新的msg插入对应的位置
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
}
msg.next = p;
prev.next = msg;
}
}
return true;
}
上面的enqueueMessage方法,主要作用就是对消息队列的一个插入处理,通过when时间先后来将新消息插入到指点的位置,说白了就是将所有在等待的消息做一个时时的排序
现在我们再来回答一下
问题1:系统在创建主线程的时候已经帮我们调用了Looper.prepare()
问题2:消息队列 mQueue 是在new Looper()的时候创建的
这里我们就要来到Activity的启动流程中分析了
4、我们来到ActivityThread类中的main方法中:
public static void main(String[] args) {
// ...
// Looper的准备工作
Looper.prepareMainLooper();
// ...
// Looper的loop方法
Looper.loop();
}
5、我们来到Looper类中:
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
// ...
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 新建一个Looper,并存放到 sThreadLocal 中
sThreadLocal.set(new Looper(quitAllowed));
}
// 新建一个Looper
private Looper(boolean quitAllowed) {
// 创建MessageQueue对象,这里就回答了上面的问题1,问题1中的mQueue就是在这里初始化的
mQueue = new MessageQueue(quitAllowed);
// 指定当前线程为 Thread.currentThread(); 就是指定当前的Looper在哪个线程中
mThread = Thread.currentThread();
}
6、我们再来看ActivityThread中的main方法里的第2个loop方法,还是来到Looper类中:
public static void loop() {
// 获取Looper.prepare()方法中创建的Looper对象
final Looper me = myLooper();
// 如果没有调用Looper.prepare()而直接调用Looper.loop()方法,就会抛出此异常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 获取消息队列 MessageQueue,这里的消息队列就是在new Looper()时创建的MessageQueue对象
final MessageQueue queue = me.mQueue;
// 开启一个死循环
for (;;) {
// 读取消息队列的next消息
Message msg = queue.next();
if (msg == null) {
return;
}
// ...
// 调用msg.target的dispatchMessage方法,这里的msg.target我们在上面2中的方法中设置为Handler
msg.target.dispatchMessage(msg);
// ...
// 调用释放msg方法
msg.recycleUnchecked();
}
}
public static @Nullable Looper myLooper() {
// sThreadLocal中获取Looper,这里获取到的Looper就是prepare方法中新建的Looper对象
return sThreadLocal.get();
}
7、来到MessageQueue类中,查看next方法
Message next() {
// 这个方法就是开一个死循环去获取消息,如果获取到就返回跳出死循环
// ...
for (;;) {
// 同步锁
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
}
}
}
}
8、我们先来到Message类中看一下recycleUnchecked方法,释放msg
void recycleUnchecked() {
// 这里就是将msg里的值置为空,以此来释放msg中存储的值
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
9、我们再来看一下msg.target.dispatchMessage(msg);也就是调用了Handler的dispatchMessage方法,我们来到Handler类中:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
// 如果mCallback不为null,则会先调用一下mCallback的handleMessage方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 然后再调用到自己的handleMessage方法
handleMessage(msg);
}
}
// 这里是一个空实现,让子类去实现
public void handleMessage(Message msg) {
}
总结:
1、Handler封装了消息的发送(主要包括消息发送给谁)
Looper
(1)内部包含一个消息队列,即MessageQueue,所有Handler发送的消息都会进入这个队列
(2)Looper.loop方法,是一个死循环,不断从MessageQueue取出消息,如有消息就处理,没有就阻塞
2、MessageQueue,一个消息队列,可以添加消息,处理消息
3、Handler内部会跟Looper进行关联,也就是说,在Handler内部可以找到Looper,找到了Looper也就找到了MessageQueue,在Handler中发送消息,其实就是向Message发送消息,
Handler负责发送消息,Looper负责接收消息,并把消息回传给Handler自己,而MessageQueue是一个存储消息的容器。