面试体记录第四节——(handler)
来源:互联网 发布:淘宝上卖的觅心猎手 编辑:程序博客网 时间:2024/06/18 04:12
一、问:什么是handler?
答:
1、可以让对应的Message和Runnable在未来的某个节点上进行相应处理(简单的来说,就是在子线程做完耗时操作,可以通过发送runnable和sendmessage方式通知主线程更新UI)。
2、让自己想要处理的耗时操作放在子线程,然后通过handler发送消息的机制,通知主线程更新UI。
二、问:handler的使用方法?
答:
1、post(runnable)
- 创建handler对象
- 开启一个子线程,在run方法中进行耗时操作。
- post源码中介绍
2、sendMessage(message)
使用方法:
第一步:在外部创建一个handler对象,并复写handleMessage()方法。如图:04
第二步:开启一个工作线程,来处理耗时操作。并且创建Message对象,通过message.what或者message.what.arg1|message.whatarg2等方式为其赋值,这个值是区分消息的类别。可以通过what的值来获取不同的message消息来更新主线程。
第三步:通过uihandler.sendMessage()方法,讲message消息传递入handler中,然后通过handerMessage()方法来进行UI线程的处理。
三、问:handler机制的原理?
答:
handler机制包含了四大部分.
1、looper:创建looper的时候,会自动创建一个MessageQueue。
如图02
2、MessageQueue:消息对列,在创建looper的时候,就已经被创建,
如图03
3、Message:消息对象。它包含了很多的参数,
4、handler:发送消息和接收消息。处理的是looper发送过来的消息。
注意:handler发送消息不能胡乱发送,它不能发送给其他线程,他只能发送到它相关的线程,也就是它相关线程的MessageQueue中。而MessageQueue有需要looper来管理。所以handler发送消息,必须有一个looper对象来维护handler。所以我们就把handler、looper、MessageQueue关联到了一起。
四、问:looper对象是怎么获取到的?
答:码中点击Looper.mylooper()来查看下looper对象是怎么来获取的。我们看到他是通过mThreadlocal.get()方法来获取
问:为什么通过mThreadlocal来获取呢?
答:mThreadlocal中,通过不同的线程,访问同一个mThreadlocal,不管使用get方法还是set方法。他们对所有mThreadlocal做的读写操作“仅限于各自线程内部”,这就是为什么handler里面要通过mThreadlocal来保存looper,这样他就可以使每一个线程有单独唯一的looper。
问:mThreadlocal.set()有是在什么时候set的呢?
答:他是在prepareMainLooper()方法中调用的(源码100行)。
他首行调用了prepare()方法。如图06,
![]()
点进去会发现,它就是创建了一个looper对象,并且把这个looper对象设置给了mThreadlocal,这样就保证了每一个线程looper的唯一。如图07
![]()
此时就可以说,整个的MessageQueue通过looper和线程关联上了。这样我们就可以在不同的线程访问不同的消息对列。
五、问:handler、looper、messageQueue在源码中怎么关联到一起的呢?
**答:如下图所示,我们发现我们通过looper.Mylooper()创建了一个looper对象。又根据成员变量looper,创建了一个mQueue。下图我们就很清晰的知道,handler在它的构造方法当中,就和messageQueue关联到了一起。而messageQueue又是通过looper,来管理的,所以。此时就可以说他们三者通过形成了handler机制。
**
六、问:为什么非要在主线程创建handler。而不能在内部类中创建handler?
就是因为每一个handler要与主线程的消息对列关联上,所以说一定要在主线程创建handler。而不能在内部类中创建handler。这样才能让handler中的handlerMessage()方法执行在UI线程。这样才能保证线程安全,不会抛出异常。
七、问:looper.loop()方法到底是什么
我们上面说,发送handler消息有两种方式,pos(runnable)和sendMessage(message),但是这两种都是运行在looper.loop()方法之后。所以我们来看下looper.loop()方法。其实loop()方法就是创建了一个for循环,然后从消息对列中逐个的去获取消息,最后处理消息。
八、问:looper源码中的详情?
答:首先它是通过prepare()方法来创建looper,把他保存在mThreadlocat中。然后通过looper.loop开启循环。最终的消息是交给target.DispatchMessage()方法来进行消息的分发,而target就是一个handler对象。
就、handler流程机制的过程是什么?
答:looper开启一个循环,从头部提取消息Meeage6,通过handlerMessage来处理消息,处理完成之后还是返回到looper中,不断的又开始循环,从消息对列中获取消息。。
- 面试体记录第四节——(handler)
- 程序员面试宝典(第四版) —— 类型转换
- 面试记录第八节——(listview面试)
- 面试记录第十二节——(Butterknife 注入框架)
- 面试记录第十四节——(什么是oom)
- 面试记录第十六节——(内存泄露)
- 面试记录第十七节——(内存管理机制概述)
- 面试记录第十九节——(MVC)
- 面试记录第二十节——(MVP讲解)
- 面试记录第二十二节——(lint检查)
- 面试记录第二十四节——(多线程)
- Android提高(14)——第四章 Handler与子线程
- 第四章 Android开发三大基石—Activity、Service和Handler(1)
- 第四章 Android开发三大基石—Activity、Service和Handler(2)
- 第四章 Android开发三大基石—Activity、Service和Handler(3)
- 第四章 Android开发三大基石—Activity、Service和Handler(4)
- 第四章 Android开发三大基石—Activity、Service和Handler(5)
- 第四章 Android开发三大基石—Activity、Service和Handler(6)
- onNewIntent调用时机
- vue页面出现正在加载的初始页面与实现动画效果
- Servlet(4)—一个简单的Servlet实例
- 使用 Navicat_premium 将 oracle 数据库迁移到 mysql
- Ueditor设置虚拟路径上传图片详解
- 面试体记录第四节——(handler)
- Timer Scheduler API参数详解
- 如何让Android TextView(包括子类)的字体大小随着字数的增加而变化,以显示全部内容
- 用C++实现HTTP服务器
- DataBinding基本使用(5)
- 【转】抓包工具Charles的使用心得
- STM32输出比较模式和PWM模式
- 开始记录深度学习工作站的学习之路
- Retrofit2高级教程 一 CompositeDisposable是否能够真的中断订阅