消息机制
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消息机制相关的知识,希望对你有一定的参考价值。
参考技术A android的消息机制是指Handler的运行机制以及Handler所附带的MessageQueue和Looper的工作过程。Handler的主要作用是将一个任务切换到某个指定的线程中去执行。Android规定访问UI只能在主线程中进行,如果在子线程中访问UI,那么程序就会抛出异常。
主线程即UI线程,它就是ActivityThread,ActivityThread被创建时就会初始化Looper,这也是主线程中默认可以使用Handler的原因。
1.Handler创建时会采用当前线程的Looper来构建内部的消息循环系统,Handler通过ThreadLocal来获取当前线程的Looper,ThreadLocal作用是可以在每个线程中存储数据;
2.Handler创建完毕后,这个时候其内部的Looper以及MessageQueue就可以和Handler一起协同工作了,通过Handler的post方法将一个Runnable投递到Handler内部的Looper中去处理,也可以通过Handler的send方法发送一个消息,这个消息同样会在Looper中处理;
3.当Handler的send方法被调用时,它会调用MessageQueue的enqueueMessage方法将这个消息放入消息队列,Looper发现有新消息到来时,就会处理这个消息,最终消息中的Runnable或者Handler的handleMessage方法就会被调用。
4.Looper是运行在创建Handler所在的线程中,这样Handler中的业务逻辑会被切换到创建Handler所在的线程中去执行了。
ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储之后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。
使用场景:android源码中会使用如Looper,ActivityThread,AMS中都用到了ThreadLocal还有就是复杂逻辑下的对象传递,比如监听器的传递。
MessageQueue主要包含两个操作,插入和读取分别对应enqueueMessage
和next,enqueueMessage的作用是往消息队列中插入一条消息,而next的作用是从消息队列中取出一条消息并将其从消息队列中移除。它是通过一个单链表的数据结构来维护消息列表。
消息循环,它会不停地从MessageQueue中查看是否有新消息,如果有新消息就会立刻处理,否则就一直阻塞在那里。
通过Looper.prepare()即可以为当前线程创建一个Looper,接着通过Looper.loop()来开启消息循环。
Looper除了prepare方法外,还提供了prepareMainLooper方法,这个方法主要是给主线程也就是ActivityThread创建Looper使用的,其本质也是通过prepare方法来实现的。Looper提供了getMainLooper方法,通过它可以在任何地方获取到主线程的Looper,Looper也可以退出,提供了quit和quitSafely方法。
Looper的loop方法是一个死循环,唯一跳出循环的方式是MessageQueue的next方法返回了null;当Looper的quit方法被调用时,Looper就会调用MessageQueue的quit或者quitSafely方法来通知消息队列退出,当消息队列被标记为退出状态时,它的next方法就会返回null。
loop方法会调用MessageQueue的next方法来获取新消息,而next是一个阻塞操作,当没有消息时,next方法会一直阻塞在那,这也导致了loop方法一直阻塞在那。
Android的主线程就是ActivityThread,主线程的入口方法为main,在main方法中系统会通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue,并通过Looper.loop()来开启主线程的消息循环。
主线程的消息循环开始了以后,ActivityThread还需要一个Handler来和消息队列进行交互,这个Handler就是ActivityThread.H,它内部定义了一组消息类型,主要包括了四大组件的启动和停止过程。
ActivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程间通信的方式完成ActivityThread的请求后会回调ApplicationThread中的Binder方法,然后ApplicationThread会向H发送
消息,H接收消息后会将ApplicationThread中的逻辑切换到ActivityThread中去执行,即切换到主线程中去执行,这个过程就是主线程的消息循环模型。
在子线程执行完耗时操作,Handler通过sendMessage发送消息后,会调用MessageQueue.enqueueMessage方法向消息队列中添加消息,然后Looper调用loop()方法开启循环后会不断地从消息队列中读取消息,然后调用目标Handler的dispatchMessage方法传递消息,然后回到Handler所在线程,目标Handler收到消息,调用handleMessage方法,接收消息,处理消息。
每个线程中只能存在一个Looper,Looper是保存在ThreadLocal中的。主线程(UI线程)已经创建了一个Looper,所以在主线程中不需要再创建Looper,但是在其他线程中需要创建Looper。每个线程中可以有多个Handler,即一个Looper可以处理来自多个Handler的消息。 Looper中维护一个MessageQueue,来维护消息队列,消息队列中的Message可以来自不同的Handler。
以上是关于消息机制的主要内容,如果未能解决你的问题,请参考以下文章