前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >笔记——安卓消息机制Handler(十六)

笔记——安卓消息机制Handler(十六)

作者头像
木溪bo
发布2019-02-25 17:18:32
5120
发布2019-02-25 17:18:32
举报

——个人平时笔记,看到的同学欢迎指正错误,文中多处摘录于各大博主与书籍精华

1、定义:Android的消息机制主要是指Handler的运行机制,Handler并不是专门用于更新UI的,它只是常被开发者用来更新UI,是同一个进程中线程间的通信机制,能够将一个任务切换到指定的线程中去执行。

Handler消息机制流程(深入探讨Android异步精髓Handlerhttps://blog.csdn.net/lfdfhl/article/details/53332936#commentBox):每一个handler的创建都必须有Looper.prepare()->new Handler()-> sendMessage()->MessageQueue->Looper.loop()->handlerMessage(),但是在UI线程是主线程中,系统会自动调用Looper.prepareMainLooper()方法创建主线程的Looper(Looper.prepare()与Looper.loop())和消息队列MessageQueue。

>1、Looper.prepare():创建一个Looper。在其内部源代码中,每一个Looper.prepare()初始化一个MessageQueue消息队列和一个线程Thread,这也是为什么很多人说的一个Handler只能持有一个MessageQueue的原因。并且由源码可知一个线程对应一个Looper也只有一个Looper.prepare(),否则会抛出异常。在prepare()内会调用sThreadLocal.set(new Looper(quitAllowed)),至于Looper,它在Android的消息机制中担负着消息轮询的角色,它会不间断地查看MessageQueue中是否有新的未处理的消息;若有则立刻处理,若无则进入阻塞

>2、sendMessage():调用handler.sendMessage()等方法发送消息,在其内部源码中都会调用enqueueMessage(MessageQueue queue, Message msg,long uptimeMillis)方法,并在其方法内部处理后调用queue.enqueueMessage(msg,uptimeMillis)方法将消息插入到消息集MessageQueue队列中,并且MessageQueue队列是遵从先进先出的原则。但是有个例外,如果调用handler.sendMessageAtFrontOfQueue()方法会直接将uptimeMillis入队列的延迟时间设置为0,所以会直接将msg插入至消息队列头部。待取出消息时优先头部取出的。如果说为什么调用sendMessage()能够准确的发送到对应的handlerMessage()接收,那是因为在enqueueMessage(MessageQueue queue, Message msg,long uptimeMillis)方法内部已经为每一个msg指定了target标签,原文“msg.target =this;”。

>3、queue.enqueueMessage(msg, uptimeMillis):将消息发送插入到MessageQueue消息队列中,uptimeMillis是发送的延迟时间。MessageQueue消息队列它的内部存储结构并不是真正的队列,而是采用单链表的数据结构来存储消息列表(单链表在插入和删除操作上效率比较高)。

>4、Looper.loop():消息的出队执行者,在loop()内部会发起一个死循环不断遍历MessageQueue内部轮询,取出消息Message msg =queue.next()next()取出一条消息并将其从消息队列中移除,直到取出的消息不为空时,才调用msg.target.dispatchMessage(msg)将消息发送到熟悉的handleMessage(msg)中接收(而msg.target=this;this即Handler本身),并在dispatchMessage方法内采用回调彻底完成线程切换。在需要的时候或事情完成后调用quit()方法停止消息的轮询,此时next()会返回null,loop()方法会结束,Looper也跟着退出,Looper退出后线程也会跟着终止。

>5、Handler在哪个线程创建,也就是运行于哪个线程,Handler的主要作用是将一个任务切换到某个指定的线程中去执行;当handler通过一系列的post或send方法发送消息到达目标线程的MessageQueue(消息队列是指定的目标线程持有的)则此时也就切换了线程。线程是默认没有Looper的,如果需要使用Handler就必须为线程创建Looper。参考:android之handler切换线程终极篇

>6、ThreadLocal并不是线程,是一个数据存储类,它的作用是可以在每个线程中存储数据。Handler创建的时候会采用当前线程的Looper来构造消息循环系统,而ThreadLocal可以在不同的线程中互不干扰地存储并提供数据,通过ThreadLocal可以轻松获取每个线程的Looper。ThreadLocal<T> mThreadLocal = new ThreadLocal<T>();mThreadLocal能够存储当前自己线程下的值,多个线程间的数据不干扰。不同线程访问同一个ThreadLocal的get方法,ThreadLocal内部会从各自的线程中取出一个数组,然后再从数组中根据当前ThreadLocal的索引去查找出对应的value值。很显然,不同线程中的数组是不同的,这就是为什么通过ThreadLocal可以在不同的线程中维护一套数据的副本并且彼此互不干扰。

小结: 1.一个线程对应一个Looper 2.一个Looper对应一个MessageQueue消息队列 3.一个线程对应一个MessageQueue消息队列 4.线程,Looper,MessageQueue消息队列三者一一对应 5.post的一系列方法最终也是通过send的一系列方法来实现的如:handler.postAtTime(),handler.sendMessageAtTime() 6.一个线程可以有多个Handler

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.01.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 CMQ 版
消息队列 CMQ 版(TDMQ for CMQ,简称 TDMQ CMQ 版)是一款分布式高可用的消息队列服务,它能够提供可靠的,基于消息的异步通信机制,能够将分布式部署的不同应用(或同一应用的不同组件)中的信息传递,存储在可靠有效的 CMQ 队列中,防止消息丢失。TDMQ CMQ 版支持多进程同时读写,收发互不干扰,无需各应用或组件始终处于运行状态。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档