Handler,Looper&&在异步线程中更新UI
来源:互联网 发布:卸载软件怎么卸载 编辑:程序博客网 时间:2024/05/29 18:28
做过Android的同学一定非常熟悉Handler和Thread在Android中的重要性。我们一般会在一个线程中执行耗时操作然后通过Handler的post()或者sendMessage()的方法将消息发送出去(此时是在异步线程)。最后就会在handleMessage()根据what来执行相关的内容或者执行相应的Runnable(UI线程)。
那么这是如何执行的呢,为什么可以从非UI线程执行到了UI线程?这里面又接触到了两个类:MessageQueue和Looper。
我们只需要看两个方法。
MessageQueue#enqueueMessage(Message msg,long when)
故名思义是将Message加入到队列中。加入的时候会通过synchronized防止同时修改,并且是根据when的时间顺序来加入的。
boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } if (msg.isInUse()) { throw new IllegalStateException(msg + " This message is already in use."); } synchronized (this) { if (mQuitting) { IllegalStateException e = new IllegalStateException( msg.target + " sending message to a Handler on a dead thread"); Log.w(TAG, e.getMessage(), e); msg.recycle(); return false; } msg.markInUse(); msg.when = when; Message p = mMessages; boolean needWake; 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 { // Inserted within the middle of the queue. Usually we don't have to wake // up the event queue unless there is a barrier at the head of the queue // and the message is the earliest asynchronous message in the queue. 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; } // We can assume mPtr != 0 because mQuitting is false. if (needWake) { nativeWake(mPtr); } } return true; }Looper#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(); } }
则是在不断的从一个死循环中读取一个Message,然后通过dispatchMessage()去分发这个Message,最后会通过相应的handleMessage()或者Runnable去执行相应的事件。
至此就完成了从异步线程耗时操作到了UI线程的UI更新。可回想一下Android中关于异步线程中更新UI的方式。
1.Handler#sendMessage()
2.Handler#post()
3.View#post()
4.Activity#runOnUiThread()
这些方式的背后最终都是通过Handler,Looper的机制来实现的。
Handler解决了跨线程之间的通信。但是也存在一些确定,其中包括对消息的暂停,恢复等等。
0 0
- Handler,Looper&&在异步线程中更新UI
- Android:在子线程中更新UI,解析异步消息处理机制(Handler)
- UI线程、Looper、Handler
- (转)Android中更新UI的线程:Thread 、Handler、Looper、TimerTask等
- Android--Android中更新UI的线程:Thread 、Handler、Looper、TimerTask
- Android--Android中更新UI的线程:Thread 、Handler、Looper、TimerTask
- [Android基础知识] 之十五: Android中更新UI的线程:Thread 、Handler、Looper、TimerTask等
- Android使用线程更新UI----Thread、Handler、Looper、TimerTask等
- Looper.prepare()和Looper.loop(),在子线程中更新UI
- 使用Handler在子线程中更新UI
- 使用Handler在子线程中更新UI
- 使用Handler在子线程中更新UI
- 使用Handler在子线程中更新UI
- 使用Handler在子线程中更新UI
- handler异步更新UI
- 使用异步消息机制在子线程中更新UI
- Android中使用Handler&Looper更新UI范例
- Android中UI线程Looper,Handler的关系
- ReactiveCocoa
- LinkedList的使用方法 && Java pop与poll的区别
- FFmpeg浅尝辄止(四)——音频的解码和编码
- windows 10(64位)下实现vs20120C++调用matlab r2014a编写的m文件生成的.dll,.lib,.h文件
- HTTP 的那些事
- Handler,Looper&&在异步线程中更新UI
- dubbo与spring mvc 整合 搭建
- 两个栈实现队列
- 详解Linux运维工程师必备技能
- PHP日期和时间处理
- 微信对话框BaseAdapter的实现
- 数据的网络请求
- java 实现word 转PDF (采用第三方技术 IText、Poi、Jsoup)
- 前端工程筹建NodeJs+gulp+bower