android艺术开发探索之消息机制
来源:互联网 发布:南昌神起网络 编辑:程序博客网 时间:2024/05/16 10:49
android艺术开发探索之消息机制
handler的工作主要包含发送消息和接受消息,通过send方法发送,发送的消息被插入到MessageQueue中,MessageQueu
e的next方法会将消息返回给looper,looper接收到消息就处理,最终looper将消息交给handler的handleMessage处理。
handler的定义:
handler真的是我们所说的那样更新ui的吗?
个人认为它是具有更新ui的功能但是不是说就是刷新ui的,handler的主要作用是将一个任务切换到某个指定的线程中去执
行。为何规定更新ui要在UI线程ActivityThread中?
ViewRootImpl对ui操作做了验证,因此只能在主线程中访问ui。但是主线程做了耗时操作会卡死出现ANR,因此将耗时操作
放在子线程。android的ui控件线程不安全,多线程并发可能导致ui处于不可预期状态,如果加锁的话会让ui访问的逻辑
变得复杂,其次锁机制会降低UI访问的效率(锁机制会阻塞某些线程的执行),因次采用单线程模型处理ui操作,也就是
使用handler切换ui访问的执行线程。主线程的消息循环模型是啥?
ActivityThread的入口方法为main,在main方法中调用Looper.prepareMainLooper()创建主线程的looper以及Message
Queue,并通过Looper.loop()开启主线程消息循环,ActivityThread.H为主线程的handler用来和消息队列进行交互,A
ctivityThread通过ApplicationThread和AMS进行进程通信,AMS以进程通信的方式回调ApplicationThread中的binder
方法,之后ApplicationThread向ActivityThread.H发送消息,ActivityThread.H收到消息将ApplicationThread的逻辑
切换到ActivityThread中执行,即切换到主线程执行。
(我不明白为何是进程通信,比如请求网络耗时操作是在子线程完成,执行过程中要刷新ui,就要切换到主线程,这怎么也
是线程之间干的事,师父说app自己不会刷,只有系统才会刷,系统和app是进程间的通信,因此其实系统默默的干了很多
事,它很累,我们在写代码的时候不用的资源要及时释放@-@!!!)
MessageQueue、Looper、ThreadLocal
MessageQueue的工作原理
内部采用单链表的数据结构存储消息队列,里面存储了一组消息,可以插入删除消息但不能处理消息,采用looper处理消息
enqueueMessage方法是往消息队列中插入一条消息,而next是取出消息并且移除,next方法是一个无限循环方法,有消息
就返回消息并从MessageQueue中移除消息,没有就一直阻塞等待。
Looper的工作原理
Looper:处理MessageQueue中的消息,有消息就处理,无消息就阻塞等待,Looper的构造器中会创建MessageQueue,并
且当前线程对象保存,利用ThreadLocal在每个线程中存储数据,handler利用ThreadLocal获取每个线程的Looper,线程默
认无Looper,我们的ActivityThread被创建时就会初始化Looper,因此主线程可以默认使用handler.
handler在创建时会使用当前线程的Looper构建内部循环系统,通过send方法发送消息到MessageQueue,Looper发现有新
消息来时就会处理,Looper是运行在handler所在的线程中的,因此handler的作用就是将一个任务切换到某个指定的线程
中去执行。
handler工作需要Looper,Looper创建如下:
new Thread(){ @Override public void run() { Looper.prepare(); Handler handler=new Handler(); Looper.loop();//只有调用此方法消息循环系统才会真正起作用,该方法死循环,跳出条件为next方法 //返回null,也就是在looper推出的时候,next方法阻塞致使looper一直阻塞 // getMainLooper();//获取主线程的Looper } }.start();
ThreadLocal的工作原理
1.ThreadLocal:它是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定的
线程中获取存储的数据,对其他的线程来说则获取不到,Looper的作用域是线程,并且不同的线程拥有不同的Looper。
2.当某些数据以线程为作用域并且不同的线程具有不同的数据副本时,就可以采用ThreadLocal,否则得写一个LooperMan
ger类了,但是系统并未这样做,这就体现了ThreadLocal的好处。
3.ThreadLocal的另一使用场景是复杂逻辑下的对象传递,比如监听器的传递,采用ThreadLocal可以让监听器作为线程
内的全局对象而存在,线程内部通过get获取监听器。
demo如下:
private ThreadLocal<Boolean> mBooleanThreadLocal=new ThreadLocal<>(); mBooleanThreadLocal.set(true); Log.e("结果", "主线程" + mBooleanThreadLocal.get()); new Thread("子线程1"){ @Override public void run() { Log.e("结果","子线程1"+mBooleanThreadLocal.get()); } }.start(); new Thread("子线程2"){ @Override public void run() { mBooleanThreadLocal.set(true); Log.e("结果","子线程2"+mBooleanThreadLocal.get()); } }.start();
打印日志如下:
08-08 11:49:25.423 2306-2306/com.efrobot.robot.autonomic E/结果: 主线程true08-08 11:49:25.431 2306-2334/com.efrobot.robot.autonomic E/结果: 子线程1null08-08 11:49:25.459 2306-2335/com.efrobot.robot.autonomic E/结果: 子线程2true
如果ThreadLocal数据不是分开的,那么子线程1的结果应该是true,但是这里却输出null,这说明了不同的线程访问同一个ThreadLocal,他们取出的是各自
线程中存储的数据,不同线程的数据互不干扰,读写操作也仅限于各自线程内部。ThreadLocal.values是专门用来存储ThreadLocal值得,底层有一个数组table,它的存储位置总是不一样的,因此取出的
值不一样。
- android艺术开发探索之消息机制
- 《Android开发艺术探索》之消息机制(一)
- 《Android开发艺术探索》--消息机制
- 开发艺术探索 -- Android中的消息机制
- 《Android开发艺术探索第十章读书笔记》-Android消息机制
- 《Android开发艺术探索》笔记(2)Android消息机制
- 《Android开发艺术探索——Android的消息机制》
- 《android开发艺术探索笔记》Part10、Android的消息机制
- 读书笔记:Android开发艺术探索之第10章 android的消息机制
- Android开发艺术探索阅读笔记之二:Android的消息机制
- Android开发艺术探索读书笔记(第10章 消息机制)
- 《Android 开发艺术探索》读书笔记六 IPC机制之Binder
- 《Android开发艺术探索》之View事件分发机制
- Android消息机制——消息队列工作原理(Android艺术开发探索读书笔记)
- Android开发艺术探索_IPC机制(二)
- Android开发艺术探索读书笔记-IPC机制
- 【读书笔记】【Android开发艺术探索】第10章 Android 的消息机制
- Android 开发艺术探索——第十章 Android的消息机制
- 计算机网络知识点汇总
- POJ 2367 Genealogical tree (拓扑排序)
- 深度学习算法实践5---线性回归算法实现
- 数学基础 —— 旋转(2D 正旋转)
- CSS-相對于父元素絕對定位
- android艺术开发探索之消息机制
- adb 和 shell、Logcat 常用命令
- leetcode_c++:Longest Common Prefix(014)
- SDUT3403数据结构实验之排序六:希尔排序
- 29. Divide Two Integers
- 使用proxifier代理LOL、橘子等游戏的教程
- 利用贝叶斯分类器进行文本挖掘---笔记
- HDU2188(巴什博奕)
- TCP、UDP区别