Handler机制一点一点带你抛析(1)
来源:互联网 发布:thinkphp开发cms 编辑:程序博客网 时间:2024/06/05 10:03
Handler机制:
原理:Handler机制是安卓提供的一套切换线程操作的工具。使用的场景:应用一般在子线程加载网络数据,然后需要将获取的数据给到视图层做展示。此过程需要切换到主线程然后做更新UI的操作。此时我们会提出一个问题:就是为什么要切换到主线程更新UI在子线程中不能更新么?
答案是不可以的。因为在ViewRootImpl类中存在一个checkThread方法用来检查View更新的线程,如果当前的线程不等于mThread指定的线程那么就会抛出异常,mThread初始化的值就是主线程。代码如下:
void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }
所以我们很容易得就可以得出结论:系统之所以提供Handler,主要原因就是为了解决在子线程中无法访问UI的矛盾。
那么Handler机制的工作原理是什么呢?这里我们先讲讲Handler的大致用法和组成。
Handler的运行需要底层Looper和Message的协助完成。Message算是存储消息的队列,每次Handler发送的消息都会存储到Message队列中。竟然消息存储在队列中,那到底谁读取队列中的信息并且运行呢?没错答案就是Looper。Looper相当于一个无限循环的While每次检查Message队列中是否存在数据,如果存在就将数据提取出来,给到Handler的HandleMessage方法进行处理调用。可以看出Looper相当于一个Handler机制的管家,每时每刻都在盯着message中是否存在数据。那么刚刚说道Handler是如何的切换线程,根据上面的解释我们好像还是有点懵懂。
切换线程的关键点还是在Looper上,看我娓娓道来。Message作为一个存储数据的是不会管当前取数据Looper管家处在什么线程。而Handler也是在不同的线程中发送数据到队列Message中。那么切换线程的工作就只能是Looper来完成了。问题一:为什么管家Looper一定是在主线程中取出数据然后给到Handler进行处理呢?
这里Looper还有一个重要的知识点,每个线程都可以创建或者持有一个Looper专门用来处理Handler发送过来的数据。并且在使用Handler之前需要在使用的线程初始化Looer,如果当前线程不存在Looper就会抛出异常,详细的看代码如下:
``` public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } 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 = callback; mAsynchronous = async;}```因为Handler与主线程的Looper进行绑定,所以Handler发送数据到队列中,再由Looper在队列中取数据时因为Looper是在主线程中取的数据,然后将数据交给之前的Handler进行处理。这个过程是在主线程的!可能这个说的有点不是很清楚。下面我会分点讨论。首先:假设我们程序中存在子线程1和主线程main,我们需要将在子线程中获取到的数据交由到主线程main中进行处理。因为这里进行了子线程的切换我们就可以使用Handler机制进行子线程1切换到主线程的操作。首先:我们需要初始化我们的Handler。整么初始化呢?一般我们直接在主线程中new Handler()---上面不是说直接new的话会报looper的缺失异常吗?因为主线程本身就存在Looper所以我们直接new 就可以。然后:我们在子线程1中将获取到的数据使用Handler发送到Message队列中。这个过程发生在子线程中。最后:由主线程的Looper取出Message队列的数据,发送给Handler进行处理--这个过程是发生在主线程中的。看懂上面的表述想必应该都大致明白Handler的机制了吧
- Handler机制一点一点带你抛析(1)
- 带你深入理解Android Handler机制
- 带你深入理解Android Handler机制
- 老司机带你了解Android的handler机制
- Handler消息机制与AsyncTask深度解析-从源码带你看handler
- 【 Android】handler异步消息处理机制完全解析,带你从源码的角度彻底理解
- 从Handler+Message+Looper源码带你分析Android系统的消息处理机制
- 江南带你从源码看handler内部实现的机制
- 从Handler+Message+Looper源码带你分析Android系统的消息处理机制
- 带你从源码看Android Handler 异步消息处理机制完全解析
- Android中handler消息处理机制完全解析,带你从源码的角度彻底理解
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解(Handler+Message处理机制)
- Handler消息传递机制(二) 教你认清Handler,Looper,MessageQueue
- Android深入--Handler机制简析(Handler、Looper、MessageQueue)
- handler(7) Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- handler机制简析
- handler机制源码层解析(1)
- Handler机制分析(1)
- ftp上传图片为空,不为空打开没法查看
- iterable,iterator和sequence
- VS C工程二【打开VC6++工程:错误1 error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏】
- Vim技巧
- 数组与指针
- Handler机制一点一点带你抛析(1)
- babyos2(3)—— console, kprintf
- hadoop源码解读二
- 二分 Evacuation
- tensorflow 版本查看命令
- 二叉树的某些性质
- JAVA变量初始化的默认值
- 输出一个爱心
- form is not define的原因-JavaScript