时间:2021-05-21
Android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在Android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的。下面就来说说最基本的东西。
Looper
作用:
关联起Thread
循环取出消息
1、Looper是否可以直接实例化?
Looper构造方法是私有的,其中做了两件事
创建一个MessageQueue
得到与之对应的Thread
2、一个线程能对应多个Lopper?
不能,一个线程对应一个Looper对象,通过ThreadLocal保证一个线程只有一个Looper与之对应,如果多次调用Looper.prepare();则会抛出运行时异常。
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { // 查看是否有looper与当前线程对应 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed));}3、Looper是无限循环,会阻塞吗?
是,当开启一个loop后是一个死循环,从MessageQueue中取出消息,处理消息,但是也有可能退出,在没有消息后退出循环。
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; // 略 for (;;) { Message msg = queue.next(); // might block if (msg == null) { // 当没有消息的时候,退出 // No message indicates that the message queue is quitting. return; }// 略 msg.target.dispatchMessage(msg); }4、可以再次调用Looper.prepareMainLooper吗?
不可以,Looper.prepareMainLooper最终也是调用prepare(),同2.
public static void prepareMainLooper() { prepare(false); // 创建一个Looper synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); }}5、MainLooper什么时候创建的?
MainLooper是启动Activity创建ActivityThread(并不是一个Thread)时候创建,所以不能多次创建。
public static void main(String[] args) { // 略 Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); // 略 ActivityThread thread = new ActivityThread(); thread.attach(false); // 略 if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } // 略 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }}Handler
作用:
发送消息到MessageQueue
处理消息
1、Handler如何与Looper、MessageQueue关联起来?
我们知道一个Looper对应一个Thread,一个Looper包含一个MessageQueue。当我们创建Handler时就会从当前线程中取出与之对应的Looper,让后在从Looper中取出MessageQueue。
// 1、自动获取public Handler(Callback callback, boolean async) { // 略 mLooper = Looper.myLooper(); // 取出当前线程中的Looper if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; // 取出MessageQueue mCallback = callback; mAsynchronous = async;}// 2、传递一个Looper进来public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }Message
单项链表结构。
作用:
数据的载体
1、消息如何复用的?
从全局消息池(链表结构)中
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();}2、Message为什么能传递?
Android中想要传递对象要么实现Serializable要么Parcelable,在这里是实现了Parcelable接口。
public final class Message implements Parcelable {
// 略
}
3、如何与Handler关联?
我们知道在消息传机制中Handler充当着“快递员”的角色,那么他又是如何与“货物”--Message发生关系呢?实际上Message有一个成员变量target他的类型正是Handler,
Runnable callback;public int arg1; public int arg2;public Object obj; Handler target; // 关键点当我们通过Handler去send一个Message时候最终都会为target赋值为this,即当前的Handler。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; // 赋值语句 if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}另为如果是通过Message.Obtain(),获取的复用Message也会为其赋值。
多说一句,Handler.obtainMessage()调用的就是Message.Obtain()。
总结:
通过一系列的包涵关系,最终Looper、Handler、Message、MessageQueue即发生关联,从而形成一个闭合,开启消息循环。
困惑
最近一直在看这方面的知识,但是能力有限,还是有不少困惑,如果有错误,或你理解下面的问题请联系我fvaryu@qq.com,愿与君交流学习,谢谢
1、Message中的sPool,哪里初始化的?为什么Message.obtain()中不会抛异常?
2、ActivityThread并不是线程,为什么可以创建一个Looper,Main Thread什么时候创建?
3、为什么序列化了的对象就可以传递?与Binder有关?
4、MessageQueue对应的是NativeMessageQueue,具体实现需要学习?
5、Loop.loop(),会退出吗?退出时机是什么?如果会退出,那么主线程同样会退出吗?
以上就是对Android 消息机制的资料整理,后续继续补充相关资料,谢谢大家对本站的支持
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例总结了Android开发中Toast显示消息的方法。分享给大家供大家参考,具体如下:Android中提供一种简单的Toast消息提示框机制,可以在用户点
Android--多线程之Handler前言 Android的消息传递机制是另外一种形式的“事件处理”,这种机制主要是为了解决Android应用中多线程的问题
本文实例讲述了Android编程中的消息机制。分享给大家供大家参考,具体如下:在分析Android消息机制之前,我们先来看一段代码:publicclassMai
大家都知道由于性能要求,Android要求只能在UI线程中更新UI,要想在其他线程中更新UI,我大致总结了4种方式,欢迎补充纠正:使用Handler消息传递机制
Android开发中经常会有倒计时的功能,下面将总结出常见的集中实现方式。1.直接使用Handler的消息机制来实现xml布局中文件如下:java代码如下:im