Android消息循环机制
来源:互联网 发布:手机淘宝链接转换器 编辑:程序博客网 时间:2024/06/05 08:48
Android消息循环机制
Android消息循环机制
Android的消息循环机制主要先关的类有:
Handler
Looper
Message
MessageQueue
ActivityThread
一、为什么用Handler
Android又不建议在主线程中做耗时操作,比如IO操作、网络请求等操作,否则容易引起程序无法响应(ANR)。所以想这些耗时操作,都会放到其他的线程中进行处理,但是非UI线程又无法操作UI,Handler的作用就是将一个任务切换到另外一个线程中执行。而我们主要用它来更新UI。
二、Handler的基本使用
1)
private Handler handler2 = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
2)
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 1:
testview.setText("处理完毕");
break;
default:
break;
}
}
};
new Thread(){
@Override
public void run() {
// 一些耗时的操作
handler.sendEmptyMessage(1);
}
}.start();
3)
handler.post(new Runnable() {
@Override
public void run() {
testview.setText("post");
}
});
4)
handler.postDelayed(new Runnable() {
@Override
public void run() {
testview.setText("postDelayed");
}
}, 5000);
三、handle使用方法分为两套:“send”方法和“post”方法。
1、send系列有7个方法,通过代码可以发现,重载方法相互调用,最终都是调用了enqueueMessage()方法。如下:
//1. 发送一个消息
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
//2. 发送一个空消息
public final boolean sendEmptyMessage(int what){
return sendEmptyMessageDelayed(what, 0);
}
//3. 定时发送一个消息
public final boolean sendEmptyMessageAtTime(int what, longuptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
//4. 延迟发送一个空的消息,内部调用了sendMessageDelayed()方法
public final boolean sendEmptyMessageDelayed(int what, longdelayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
//5. 发送一个消息到消息队列的头部
public final boolean sendMessageAtFrontOfQueue(Message msg) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with nomQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, 0);
}
// 6. 定时发送一个消息
public boolean sendMessageAtTime(Message msg, long uptimeMillis){
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with nomQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
//7. 延迟delayMillis时间发送一个消息
public final boolean sendMessageDelayed(Message msg, longdelayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() +delayMillis);
}
2、post系列有5个方法,代码中可以看出,post的这几个方法都是调用的send的先关方法。只不过通过getPostMessage()的几个重载方法,将Runnable封装成了Message,代码如下:
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postDelayed(Runnable r, long delayMillis){
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean postAtTime(Runnable r, long uptimeMillis){
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtFrontOfQueue(Runnable r){
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
public final boolean postAtTime(Runnable r, Object token, longuptimeMillis){
return sendMessageAtTime(getPostMessage(r, token),uptimeMillis);
}
3、来看看getPostMessage的重载方法:
/**
* 设置消息对象的callback,返回Message对象
*当调用dispatchMessage()方法的时候,判断Message的callback是否为空,不为空时,调用callback的run()方法。
*/
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
/**
* 将Runnable和Object封装成一个Message对象返回。
*/
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
一共有两个,都是通过Message.obtain()方法获取一个消息对象,然后重新对内部变量赋值,然后返回该Message对象。
3、不管是post方法,还是send方法,最后都牵扯到enqueueMessage这样一个方法。该方法内部,将message的target赋值为当前Handler对象,可见target是Handler类型的对象。最后调用了queue.enqueueMessage()对象。queue是MessageQueue类型的变量,表示一个消息队列。消息队列实际上是通过单链表的结构来实现的。其内部逻辑,就是通过对when和当前对头指针的一些判断逻辑,进而将参数中的message添加到单单链表中。
/**
* 将message添加到消息队列
*/
private boolean enqueueMessage(MessageQueue queue, Message msg,long uptimeMillis) {
msg.target = this; // 这里将message的target对象赋为handler
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
/**
* 消息入队操作
*/
boolean enqueueMessage(Message msg, long when) {
// ...
synchronized (this) {
// ...
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
//当mMessage为空或者when是0后者when小于对头的when值时,将当前msg作为对头。
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// 当msg添加到队列中间。
needWake = mBlocked && p.target == null &&msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// ...
}
return true;
}
四、总结
当我们使用Handler的时候,通过post或者send的一些列方法(post方法通过通过getPostMessage()方法将Runnable封装成Message对象调用send系列的方法实现,而getPostMessage()方法则调用Message.obtain()方法获取一个消息对象,不是立马创建一个消息对象,而是从消息池中获取,如果有就复用,没有就重新创建),把一个Message(消息)添加到MessageQueue(消息队列)中去,内部是单向链表。
五、Looper
Looper可以称之为“消息循环”。其主要作用是:当我们将消息放到消息队列之后,通过Looper管理消息队列,从队列中取出消息进行处理。
首先,Looper的构造函数是private类型,只能通过prepare(boolean)方法来进行初始化,并在构造函数中完成消息队列MessageQueue的初始化。如:主线程也就是ActivityThread,创建的时候会调用ActivityThread.main()方法,进而调用Looper.prepareMainLooper()——>Looper.prepare(boolean)方法,完成Looper对象的初始化(new了一个Looper对象),Looper的私有构造函数中正好创建了一个消息队列。一个线程只允许存在一个looper对象,否则会出现运行时异常,并通过ThreadLocal保存looper对象。
其次,当创建好looper对象后,然后通过Looper.loop()分发消息。loop()方法实际上建立了一个消息循环(死循环),一直从消息队列中读取消息,然后调用Message的target对象,实际上就是Handler对象的dispatchMessage(msg)方法进行处理。
六、Looper创建
首先,Looper的构造函数是private类型,只能通过prepare(boolean)方法来进行初始化,并在构造函数中完成消息队列MessageQueue的初始化。如:主线程也就是ActivityThread,创建的时候会调用ActivityThread.main()方法,进而调用Looper.prepareMainLooper()——>Looper.prepare(boolean)方法,完成Looper对象的初始化(new了一个Looper对象),Looper的私有构造函数中正好创建了一个消息队列。一个线程只允许存在一个looper对象,否则会出现运行时异常,并通过ThreadLocal保存looper对象。代码如下:
ActivityThread.Java 的部分源码:
static Handler sMainThreadHandler; // set once in main()
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"ActivityThreadMain");
//...
Process.setArgV0("<pre-initialized>");
//初始化当前线程为looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//开始运行线程中的消息队列 -- message queue
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedlyexited");
}
Looper类部分源码:
static final ThreadLocal<Looper> sThreadLocal = newThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
//系统调用此方法,初始化当前线程为looper,作为一个应用程序的主looper。
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper hasalready been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//一个线程只允许存在一个looper对象。
throw new RuntimeException("Only one Looper may becreated per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
//Looper构造函数--私有化
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//返回绑定到当前线程上的Looper对象
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
七、Looper分发消息
当创建好looper对象后,然后通过Looper.loop()分发消息。loop()方法实际上建立了一个消息循环(死循环),一直从消息队列中读取消息,然后调用Message的target对象,实际上就是Handler对象的dispatchMessage(msg)方法进行处理。
代码如下:
public static void loop() {
final Looper me = myLooper();
if (me == null) {//如果me是null,则表示没有调用prepare()方法。
throw new RuntimeException("No Looper; Looper.prepare()wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;// 1. 获取消息队列
// ...
for (;;) { // 2. 消息循环
Message msg = queue.next(); // 3. 获取消息(从消息队列中阻塞式的取出Message)
if (msg == null) {
// No message indicates that the message queue isquitting.
return;
}
// ...
//Message对象内部有一个Handler对象target。故,实际上调用的handler的dispatchMessage
// 故,实际上调用的handler的dispatchMessage(msg)方法进行分发。
msg.target.dispatchMessage(msg); // 4. 分发处理消息
if (logging != null) {
logging.println("<<<<< Finished to "+ msg.target + " " + msg.callback);
}
// ...
msg.recycleUnchecked();// 5. 回收消息
}
Handler.dispatchMessage(msg);
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {// 当message对象中Runnable类型的callback不为空时
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); // 调用重写的方法
}
}
// 调用runnable类型的run()方法
private static void handleCallback(Message message) {
message.callback.run();
}
// 实现该接口时,重写该方法。
public interface Callback {
public boolean handleMessage(Message msg);
}
// 使用Handler的时候,会重写该方法。
public void handleMessage(Message msg) {
}
八、Handler构造:
Handler有几个构造重载,如果构造时不提供Looper类对象参数,会获取当前线程的Looper对象,即将当前线程的消息循环作为Handler关联的消息循环。
不是所有线程都有一个消息循环,主线程默认有looper对象,其他线程需要显式的创建作为参数传递给handler对象。如果当前线程没有looper,而构造Handler对象时又没有指定Looper对象,则会抛出一个运行时异常:
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException("Can't create handler insidethread that has not called Looper.prepare()");
}
九、综述:
如图
1)程序启动的时候,主线程会创建一个Looper对象。Looper对象内部维护一个MessageQueue,然后调用loop()方法循环去读取消息。
具体操作如下:首先,Looper的构造函数是private类型,只能通过prepare(boolean)方法来进行初始化,并在构造函数中完成消息队列MessageQueue的初始化。如:主线程也就是ActivityThread,创建的时候会调用ActivityThread.main()方法,进而调用Looper.prepareMainLooper()——>Looper.prepare(boolean)方法,完成Looper对象的初始化(new了一个Looper对象),Looper的私有构造函数中正好创建了一个消息队列。一个线程只允许存在一个looper对象,否则会出现运行时异常,并通过ThreadLocal保存looper对象。
其次,当创建好looper对象后,然后通过Looper.loop()分发消息。loop()方法实际上建立了一个消息循环(死循环),一直从消息队列中读取消息,然后调用Message的target对象,实际上就是Handler对象的dispatchMessage(msg)方法进行处理。
2)初始化Handler的时候,在Handler的构造函数内部,会获取当前线程的Looper对象,进而获取MessageQueue对象。由此可见,想要操作UI的Handler必须在主线程中创建。
3)调用Handler的相关发送消息方法时,会获取Message对象,将消息对象的target指向当前handler对象,然后放到消息队列中。Message内部维护一个消息池,用来回收缓存message对象。
当我们使用Handler的时候,通过post或者send的一些列方法(post方法通过通过getPostMessage()方法将Runnable封装成Message对象调用send系列的方法实现,而getPostMessage()方法则调用Message.obtain()方法获取一个消息对象,不是立马创建一个消息对象,而是从消息池中获取,如果有就复用,没有就重新创建),把一个Message(消息)添加到MessageQueue(消息队列)中去,内部是单向链表。
4)loop()工作中,会从消息队列中获取一个个的消息,调用handle的dispatchMessage(msg)分发处理。
参考http://www.2cto.com/kf/201606/518409.html
- Android消息循环机制
- Android消息循环机制
- Android消息循环机制
- Android消息循环机制
- Android 线程消息循环机制
- Android 线程消息循环机制
- Android消息循环机制总结
- Android消息循环机制探讨
- Android消息循环机制分析
- android Toast、Looper、Handler消息循环机制
- Android 消息循环机制源码分析
- Android 消息循环机制源码分析
- Android 消息循环机制源码分析
- Android 消息循环机制源码分析
- Android消息循环机制源码分析
- android应用消息处理机制分析之消息循环
- SDK消息循环机制
- windows 消息循环机制
- 如何使用Charles抓包并分析Http报文
- java synchronized关键字的用法以及锁的等级:方法锁、对象锁、类锁
- vue表单自定义校验规则
- android 7.0 因为Uri.fromFile引起的FileUriExposedException异常
- Win7 BitLocker加密须了解的五件事
- Android消息循环机制
- 并发操作子线程
- spaarkr 的使用
- Bayesian Network
- (1)、JEasyUI 之 Datagrid的Combobox 显示 textField 值的问题
- [日推荐] 『好奇心日报』满足你所有的好奇心
- Robotframework(2):创建RF第一条可执行的用例
- 8-23 DAIRY
- 连通性问题(connectivity)