面试体记录第四节——(handler)
一、问:什么是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机制。
**