美文网首页
Handler消息异步通信机制

Handler消息异步通信机制

作者: Davisxy | 来源:发表于2019-03-31 15:43 被阅读0次
    • Handler实例化的时候,在里面获取了Looper;通过调用Looper.myLooper()方法;
    • Looper在创建的时候先调用Looper.prepare()方法;然后在里面实例化一个Looper对象,并存储到线程本地变量里面;并且设置了一个判断条件,如果在本地线程变量里面获取到Looper的实例就抛出异常,说明Looper.prepare()在一个线程中只能调用一次;
    • 在Looper的构造方法当中,传入了一个是否允许退出的标志(主要用于主线程/UI线程,怎么能允许退出呢?主线程都推出了还玩什么),在构造方法中又实例化了一个消息队列(说明每个线程只有一个消息队列),并获取到了当前线程;
    • Handler实例化之后,开始发消息,消息最终都发到了消息队列中(enqueueMessage(Message msg,long when))中,这中间过程中将Handler的实例引用指向了Message的一个变量中,叫做target;
    • 这时候启动Looper.loop()方法,开始去循环消息队列,按照时间的顺序,检查消息的有效性等一些判断条件,然后后将消息通过Message中的target(也就是Handler)分发到回调中,就是dispatchMessage(Message msg)方法;
    • 在dispatchMessage(Message msg)这个回调方法中又有三个回调,这三个回调取决于是怎么发送消息的;
      • 优先级最高的就是通过new Handler().post(Runnable runnable);方式,他会调用handleMessage方法,最终调用message.callback.run()回调方法;
      • 其次是通过new Handler(Callback callback,boolean ansyc)这类设置了Callback的方式,会回调这个接口本身的handleCallback(Message msg)方法,这个接口方法有返回值,如果返回false,则分发结束,true则执行handleMessage(Message msg)这个空方法;
      • 像我们平时普通用的new Handler()这种无参构造,最终就是调用的这个handleMessage(Message msg),因为Callback和Runnable都是空的;
    • Handler是怎么完成线程切换的呢?
      • 首先,我们最常用的在主线程中创建一个无参构造Handler,这时候Looper就会直接取线程本地变量,和我们说的流程我们少了一步,就是Looper.prepare()方法的调用,这个方法不是没调用,而是在主线程启动的时候就已经调用了,并绑定到了主线程,所以MessageQueue是在主线程中创建的,也就是说无论是在子线程还是主线程中发消息,那他的消息最终也就分发到了主线程;
      • 第二种,就是我们在子线程中创建无参Handler,这时候就会报错,因为Looper.prepare()还没有调用,调用后绑定了当前子线程,并在子线程中创建了Message,这样消息最终的回调还是在子线程;你可以再主线程中或者任何一个子线程中发消息,最终在这个子线程中接收;
      • 第三种,就是指定Looper, 无非两种情况,一个就是在子线程中Looper.prepare()创建一个Looper,这样消息队列还是在子线程,最终的回调还是在子线程;另一种就是传入主线程的Looper:传入looper.getMainLooper()方法,最终的回调在主线程中;
      • 这也就说明了Handler在哪里创建并不重要,重要的是看他的Looper是在哪里创建的;

    相关文章

      网友评论

          本文标题:Handler消息异步通信机制

          本文链接:https://www.haomeiwen.com/subject/dbtubqtx.html