趁着有时间,看看Android源码,先来看看Handler,后期的时候在更新吧。都忘记了上次看源码是什么时候了。废话不哆嗦了,先了解下Handler是干嘛的,内容简介啊,原理啊,里面实现的方法啊,涉及到的设计模式啊,我进来满足大家,给大家展示,至于写个什么样的demo我还没想好,不过网上很多了,可以自己去寻找寻找。开始搞起~
一.Handler 讲什么的?
每个Handler实例都与一个线程和该线程的消息队列相关联。当您创建一个新的Handler时,它被绑定到创建它的线程/消息队列 ——从那开始,它将传递消息发送该消息队列中,并在消息队列结束时执行它们。
二.我们主要拿来干嘛呢?
两件事儿能干:
1.调度消息和代码,以便在将来的某个时间执行;
2.对要在不同于您自己的线程上执行的操作进行查询;
三.简单的画了一个图,理解一下Handler+Looper+Message+MessageQueue的工作原理
通俗来讲:
1.创建一个Handler,然后Handler发送一个消息(Message)放在消息队列(MessageQueue)中。
2.通过Looper的死循环,然后不断的从消息队列中去消息,然后处理消息。
3.处理完的消息,通过Handler的handlerMessage或者是CallBack方法来回调给Handler。
这样整个过程就完成了。
四. 我们看下Handler中提供的构造方法
1.public Handler()
默认构造函数将此处理程序与当前线程的Looper关联。如果该线程没有循环器,则此处理程序将无法接收消息,因此会引发异常。
2.public Handler(Callback callback)
构造函数将此处理程序与当前线程的队列关联,并接受一个可在其中处理消息的回调接口。
3.public Handler(Looper looper)
使用提供的队列而不是默认队列。
4.public Handler(Looper looper, Callback callback)
使用提供的队列而不是默认队列,并进行回调接口,在其中处理消息。
五.看看里面我们常用的几个方法的实现;
1.handler的sendMessage()
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
sendMessage 里面实现的是一个sendMessageDelayed,那我们继续看看他的源码吧;
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
其中的2个参数,一个是传递的消息Message、 另外的是我们要执行的延迟时间;按照源码中的提示,接着看看下面的sendMessageAtTime方法;
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
啊哈,终于可以看到最终的实现了,简单的分析一下:
先看看我们创建的MessageQueue中是否有未处理的消息,之后要看的就是enqueueMessage方法的返回值来判断是否成功。看看这个方法搞什么呢?
在MessageQueue中的源码看到这个方法如下;
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
1.我们来看下if里面的条件,如果mMessages对象为空,或者when为0也就是立刻执行,或者新消息的when时间比mMessages队列的when时间还要早,符合以上一个条件就把新的msg插到mMessages的前面 并把next指向它,也就是msg会插进上图中队列的最前面,等待loop的轮询。
2.如果上面的条件都不符合就进入else代码中,我们可以看到17行是有个for的死循环遍历已有的message对象,其中第20行中有个if语句when < p.when when是新消息的执行时间,p.when的是队列中message消息的执行时间,如果找到比新的message还要晚执行的消息,就执行 msg.next = p; prev.next = msg; 也就是把插到该消息的前面,优先执行新的消息。
其实Handler总结到这里,我也不知道该说什么了,简单的分享一个demo,大家都会的,也让大家理解一下Handler的应用吧,实现一个倒计时功能;哈哈哈
eg:
在MainActivity中创建一个Handler,然后实现倒计时。代码如下:
private static int TIME = 5;
private TextView mTime;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
TIME--;
mTime.setText(TIME + "s");
if (TIME > 0) {
Message message = handler.obtainMessage(1);
handler.sendMessageDelayed(message, 1000);
}
}
super.handleMessage(msg);
}
};
学习的时光总是要花费的,希望大家喜欢我的分享;我的公众号也可以关注哦。扫码下面的二维码即可;