Android 消息机制问题总结
android的消息机制几乎是面试必问的话题,当然也并不是因为面试,而去学习,更重要的是它在android的开发中是必不可少的,占着举足轻重的地位,所以弄懂它是很有必要的。下面就来说说最基本的东西。
looper
作用:
关联起thread
循环取出消息
1、looper是否可以直接实例化?
looper构造方法是私有的,其中做了两件事
创建一个messagequeue
得到与之对应的thread
private looper(boolean quitallowed) { mqueue = new messagequeue(quitallowed); mthread = thread.currentthread(); }
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,
/*package*/ runnable callback; public int arg1; public int arg2; public object obj; /*package*/ 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()。
public final message obtainmessage(){ return message.obtain(this); }
总结:
通过一系列的包涵关系,最终looper、handler、message、messagequeue即发生关联,从而形成一个闭合,开启消息循环。
困惑
最近一直在看这方面的知识,但是能力有限,还是有不少困惑,如果有错误,或你理解下面的问题请联系我,愿与君交流学习,谢谢
1、message中的spool,哪里初始化的?为什么message.obtain()中不会抛异常?
2、activitythread并不是线程,为什么可以创建一个looper,main thread什么时候创建?
3、为什么序列化了的对象就可以传递?与binder有关?
4、messagequeue对应的是nativemessagequeue,具体实现需要学习?
5、loop.loop(),会退出吗?退出时机是什么?如果会退出,那么主线程同样会退出吗?
以上就是对android 消息机制的资料整理,后续继续补充相关资料,谢谢大家对本站的支持