面试体记录第四节——(handler)

一、问:什么是handler?

答:

1、可以让对应的Message和Runnable在未来的某个节点上进行相应处理(简单的来说,就是在子线程做完耗时操作,可以通过发送runnable和sendmessage方式通知主线程更新UI)。

2、让自己想要处理的耗时操作放在子线程,然后通过handler发送消息的机制,通知主线程更新UI。


二、问:handler的使用方法?

答:

1、post(runnable)

  • 创建handler对象

面试体记录第四节——(handler)

  • 开启一个子线程,在run方法中进行耗时操作。

面试体记录第四节——(handler)

  • post源码中介绍

面试体记录第四节——(handler)

2、sendMessage(message)

使用方法:

第一步:在外部创建一个handler对象,并复写handleMessage()方法。如图:04
面试体记录第四节——(handler)

第二步:开启一个工作线程,来处理耗时操作。并且创建Message对象,通过message.what或者message.what.arg1|message.whatarg2等方式为其赋值,这个值是区分消息的类别。可以通过what的值来获取不同的message消息来更新主线程。

面试体记录第四节——(handler)

第三步:通过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关联到了一起。
面试体记录第四节——(handler)


四、问:looper对象是怎么获取到的?

答:码中点击Looper.mylooper()来查看下looper对象是怎么来获取的。我们看到他是通过mThreadlocal.get()方法来获取

面试体记录第四节——(handler)

  • 问:为什么通过mThreadlocal来获取呢?

    答:mThreadlocal中,通过不同的线程,访问同一个mThreadlocal,不管使用get方法还是set方法。他们对所有mThreadlocal做的读写操作“仅限于各自线程内部”,这就是为什么handler里面要通过mThreadlocal来保存looper,这样他就可以使每一个线程有单独唯一的looper。

  • 问:mThreadlocal.set()有是在什么时候set的呢?

答:他是在prepareMainLooper()方法中调用的(源码100行)。

他首行调用了prepare()方法。如图06,
面试体记录第四节——(handler)
点进去会发现,它就是创建了一个looper对象,并且把这个looper对象设置给了mThreadlocal,这样就保证了每一个线程looper的唯一。如图07
面试体记录第四节——(handler)
此时就可以说,整个的MessageQueue通过looper和线程关联上了。这样我们就可以在不同的线程访问不同的消息对列。


五、问:handler、looper、messageQueue在源码中怎么关联到一起的呢?

**答:如下图所示,我们发现我们通过looper.Mylooper()创建了一个looper对象。又根据成员变量looper,创建了一个mQueue。下图我们就很清晰的知道,handler在它的构造方法当中,就和messageQueue关联到了一起。而messageQueue又是通过looper,来管理的,所以。此时就可以说他们三者通过形成了handler机制。

**
面试体记录第四节——(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)

面试体记录第四节——(handler)


就、handler流程机制的过程是什么?

答:looper开启一个循环,从头部提取消息Meeage6,通过handlerMessage来处理消息,处理完成之后还是返回到looper中,不断的又开始循环,从消息对列中获取消息。。

面试体记录第四节——(handler)

面试体记录第四节——(handler)