Android Handler
来源:互联网 发布:淘宝宝贝搜索不到 编辑:程序博客网 时间:2024/05/17 09:33
Android Handler
参考
Android消息机制1-Handler(Java层)
Android异步消息处理机制完全解析,带你从源码的角度彻底理解
对于线程是一段可以执行线程内部的代码,当可执行的代码执行完毕 当前线程的生命周期就终止,线程退出
对于主线程绝对不希望自己就退出 需要他一直处于可执行的状态 ———————— 死循环 既可以最方便解决这个方案
真正会导致主线程出现ANR的 既是onCreate,onStrat()等方法执行时间过长导致出现的
这样就达到子线程可以唤醒UI线程(主线程),而且主线程不会因为是死循环的原因一直抢夺CPU的执行权 浪费CPU资源
- Handler机制原理分析
界面绘制与更新只能在UI线程中操作 如果子线程想要更新UI界面需要使用Hnadler机制
使用Handler机制需要使用到Hnadler,Looper,MessageQueen这三个对象
异步操作标准写法
class LooperThread extends Thread { public Handler mHandler;//全局Hanler 方便其他线程引用到这个对象 public void run() { Looper.prepare();//创建Looper对象 所有的Handler操作都需要Looper对象 mHandler = new Handler() { public void handleMessage(Message msg) { // 获取到其他线程发来的Mesage消息 } }; Looper.loop();//死循环遍历消息 } }
其他线程发送消息到上面线程上
handler.sendMessage(Message msg); handler.sendxxxx
这些方法最后都会调用到
参数1:Mesage信息 参数2:发送时间 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue;//消息队列 if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis);//Message信息入队列 } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; }
- Looper.prepare()
每个子线程只可以创建一个looper对象 如果在TSL区域中有looper对象 将会抛出异常
private static void prepare(boolean quitAllowed) { //每个线程只允许执行一次该方法,第二次执行时线程的TLS已有数据,则会抛出异常。 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } //创建Looper对象,并保存到当前线程的TLS区域 sThreadLocal.set(new Looper(quitAllowed)); }
ThreadLocal: 线程本地存储区(Thread Local Storage,简称为TLS),每个线程都有自己的私有的本地存储区域,不同线程之间彼此不能访问对方的TLS区域。TLS常用的操作方法:
ThreadLocal.set(T value):将value存储到当前线程的TLS区域,源码如下:
public void set(T value) { Thread currentThread = Thread.currentThread(); //获取当前线程 Values values = values(currentThread); //查找当前线程的本地储存区 if (values == null) { //当线程本地存储区,尚未存储该线程相关信息时,则创建Values对象 values = initializeValues(currentThread); } //保存数据value到当前线程this values.put(this, value); }
ThreadLocal.get():获取当前线程TLS区域的数据,源码如下:
public T get() { Thread currentThread = Thread.currentThread(); //获取当前线程 Values values = values(currentThread); //查找当前线程的本地储存区 if (values != null) { Object[] table = values.table; int index = hash & values.mask; if (this.reference == table[index]) { return (T) table[index + 1]; //返回当前线程储存区中的数据 } } else { //创建Values对象 values = initializeValues(currentThread); } return (T) values.getAfterMiss(this); //从目标线程存储区没有查询是则返回null }
ThreadLocal的get()和set()方法操作的类型都是泛型,接着回到前面提到的sThreadLocal变量,其定义如下:
static final ThreadLocal sThreadLocal = new ThreadLocal()可见sThreadLocal的get()和set()操作的类型都是Looper类型> 把Looper存储到线程TSL中 方便之后取出Looper对象 Looper构造函数中创建当前线程唯一的MessageQueen对象* 入队
参数1:Mesage信息 参数2:发送时间 final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { if (mQuiting) { RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } msg.when = when; Message p = mMessages; if (p == null || when == 0 || when
总结
- Handler通过sendMessage()发送Message到MessageQueue队列;
- Looper通过loop(),不断提取出达到触发条件的Message,并将Message交给target来处理;
- 经过dispatchMessage()后,交回给Handler的handleMessage()来进行相应地处理。
- 将Message加入MessageQueue时,处往管道写入字符,可以会唤醒loop线程;如果MessageQueue中没有Message,并处于Idle状态,则会执行IdelHandler接口中的方法,往往用于做一些清理性地工作。
这样就做到子线程可以操控主线程更新UI
上诉的论述中可知 主线程是处于死循环中 因为这样就可以避免主线程退出 可以大胆推测出整个App进程中操作UI线程中采用Handler机制 获取来自其他线程的消息 然后使UI线程做出相对应的消息
- 论证
ActivityThread的内部类H继承于Handler,通过handler消息机制 从其他子线程中获取Message消息 解析Mesage消息 常用的有Activity的生命周期的调度 比如收到msg=H.LAUNCH_ACTIVITY,则调用ActivityThread.handleLaunchActivity()方法,最终会通过反射机制,创建Activity实例,然后再执行Activity.onCreate()等方法;
再比如收到msg=H.PAUSE_ACTIVITY,则调用ActivityThread.handlePauseActivity()方法,最终会执行Activity.onPause()等方法
但是谁发送这些Message消息给主线程的队列中?
IPC机制一般都运用到C/S架构上
system_server进程是系统进程,java framework框架的核心载体,里面运行了大量的系统服务,比如这里提供ApplicationThreadProxy(简称ATP),ActivityManagerService(简称AMS),这个两个服务都运行在system_server进程的不同线程中,由于ATP和AMS都是基于IBinder接口,都是binder线程,binder线程的创建与销毁都是由binder驱动来决定的。
ActivityManagerService 活动管理者服务 用来管控Activity的生命周期的调度和创建 但是他是在System_service进程中 需要通过ATP来通过 Binder方式传递信息到当前需要调度Activity的App进程中上的ApplicationThread上 在ApplicationThread通过Hnadler机制唤醒主线程 主线程的hanlerMessage(Message msg)方法上解析出操作的请求 做出对应的操作 完成一次生命周期的调度
- android Handler
- android Handler
- android Handler
- android Handler
- Android Handler
- android---handler
- android-handler
- Android Handler
- Android Handler
- Android Handler
- android Handler
- android--Handler
- Android Handler
- Android Handler
- Android Handler
- Android Handler
- Android handler
- Android Handler
- 收缩导航条
- Scrapy爬虫中使用Splash处理页面JS
- 6、抽象类与接口
- SDWebImage源码分析
- onCreate()方法中获取View的宽高为0的原因及解决方法
- Android Handler
- CentOS、Rhel永久修改hostname
- 数据结构实验之链表七:单链表中重复元素的删除
- [前端]
- Android 编写文件浏览器
- eclipse中部署opencms进行调试
- iOS run loop(NSRunLoop)和线程的一些需要注意的细节
- 如何应付重度反爬虫的网站
- 学习Android动画小结