《安卓笔记》Handler消息机制
来源:互联网 发布:java waitfor 返回值1 编辑:程序博客网 时间:2024/05/21 14:56
Handler消息机制
Message 消息
Message.obtain()Message msg = new Message()
Handler
new Handler(){ handlerMessage(Message msg){ // 处理消息 }}
Handler的构造方法:
public Handler() { ... // 获取looper mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; }
主线程设置Looper,在ActivityThread类里面
public static final void main(String[] args) { .... // 1.主线程创建Looper Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop();
Looper
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 3、在主线程中设置Looper, new Looper()里面创建了一个MessageQueue sThreadLocal.set(new Looper()); public static final void prepareMainLooper() { // 2、调用prepare prepare(); setMainLooper(myLooper()); if (Process.supportsProcesses()) { myLooper().mQueue.mQuitAllowed = false; } }
主线程调用Looper.loop()方法,主线程就会阻塞,是一个死循环,使用管道(Pipe),是Linux中的一种进程间通信方式,使用了特殊的文件,有两个文件描述符(一个是读取,一个是写入)
应用场景;主进程拿着读取描述符等待读取,没有内容时就阻塞,另一个进程拿写入描述符去写内容,唤醒主进程,主进程拿着读取描述符读取到内容,继续执行。
Handler应用场景:Handler在主线程中创建,Looper会在死循环里等待取消息,1、没取到,就阻塞,2、一旦被子线程唤醒,取到消息,就把Message交给Handler处理。子线程用Handler去发送消息,拿写入描述符去写消息,唤醒主线程。
public static final void loop() { ... while (true) { // 取消息,如果没有消息,就阻塞 Message msg = queue.next(); // might block ... msg.target.dispatchMessage(msg); ... } }
Handler发送消息代码
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { .... // 把Message的target置为当前发送的Handler,以便Looper取到message后根据target把message分发给正确的Handler msg.target = this; // 往队列里面添加Message sent = queue.enqueueMessage(msg, uptimeMillis); .... }
MessageQueue.enqueueMessage 代码
final boolean enqueueMessage(Message msg, long when) { ... Message p = mMessages; if (p == null || when == 0 || when < p.when) { // 当前发送的message需要马上被处理调,needWake唤醒状态置true msg.next = p; mMessages = msg; needWake = mBlocked; // new head, might need to wake up } else { // 当前发送的message被排队到其他message的后面,needWake唤醒状态置false Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; needWake = false; // still waiting on head, no need to wake up } } // 是否唤醒主线程 if (needWake) { nativeWake(mPtr); } return true;
Handler.dispatchMessage方法
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } // 把Message交给Handler处理 handleMessage(msg); } }
总结
每个应用被创建都会在主线程设置一个Looper,并在new Looper()里创建一个messageQueue,当Looper被创建之后就会调用Looper.loop(),这是一个死循环,里面用到了一个pipe(管道)的进程间通讯方式,有2个文件描述符, 一个写入,一个读取。
当handler.sendMessage(msg)的时候,msg会把msg.target置位当前的handler,以便后面Looper取到消息的时候能根据target将msg分给对应的handler。然后handler就会把 msg添加到messageQueue里,messageQueue会调用enqueueMessage 拿到写入文件描述符往里面写入消息,将msg按照时间排序,消息队里是先进先出 的方式。
Looper.loop()方法里面会调用queue.next()拿到读取的文件描述符,不断的去消息队列取消息,如果取到消息就调用msg.target.diapatchMessage(msg),将消息发给handler处理。
0 0
- 《安卓笔记》Handler消息机制
- 安卓Handler消息机制
- 安卓handler消息处理机制
- 安卓Handler消息机制的例子
- 安卓基础:Handler消息传送机制
- 安卓中的handler消息传递机制
- 安卓Handler,Looper消息传递机制
- 安卓handler消息机制源码解析
- Handler消息机制笔记
- 【安卓开发艺术探索】第10章 消息机制Handler 笔记
- 安卓开发中Handler消息传递机制
- 安卓开发:Handler异步消息处理机制使用
- 安卓中的消息循环机制Handler及Looper详解
- 安卓消息处理机制(Looper,Handler,Message)
- 安卓Handler机制
- 学习笔记-Handler消息机制
- xamarin学习笔记A13(安卓Handler异步消息处理)
- 安卓消息机制
- Centos6.5 安装 jsoncpp
- Effective Java item6 消除过期对象的引用
- php 导出 Excel
- 查看浏览器的内核
- HDFS 基本文件操作API
- 《安卓笔记》Handler消息机制
- Android ListView相关开源项目汇总
- 内存分配失败
- NLM去噪算法实现
- 开启博客之旅
- Log的五种信息
- 动态代理记录日志
- {小结}GDOI2016骗分记
- 【翻译】ContentProviderClient VS ContentResolver