Handler原理分析

来源:互联网 发布:linux pyqt4 安装 编辑:程序博客网 时间:2024/06/05 19:25
Message 实现了Parcelable 接口   可以被IPC传递
有单例模式的获取Message
序列化以及读取方法
自身带有一些参数  如 what  target(handler)   callback(Runnable) 等
使用池 缓存模式    next 指向下一个缓存目标  
缓存池 设计较为简单   
1.首先在第一次使用的时候因为没有缓存 所以只能new一个Message
2.当使用结束后 会将该Message 的next 指向池首Message(第一次回收的时候 池首Message为null),然后再把该Message设置为池首Message(设置为池首Message之前已经讲相关参数状态等重置)
3.再次使用的时候会在缓存池中取出
4.如果这时候还需要新的Message对象就只能new一个出来
5.在回收的时候会将两个Message都放入池中  
6.设置了一个flag  规定了缓存池中Message缓存的最大个数,超过这个个数会等待JVM自动回收




Message 中存在target 和CallBack  
回调的时候是使用target(handler)中的dispatchMessage(Message msg)方法  根据该方法的if else if 的判断   可以得到消息处理的优先级顺序
1.Message中的Runnable   CallBack
2.Handler 中Callback  接口
3.handleMessage  new Handler时实现的方法
按照顺序来寻找 前面的处理了后面的就不会被调用到




MessageQueue  比起Message要复杂一些  他需要调用一些native方法   
作用就是用于存储消息,其中含有同步阻塞器(所以一些重要的需要优先执行的都是异步)
MessageQueue的核心方法是next(),这个方法用于返回一个需要处理的Message。
在next()方法中存在一个死循环,用来不断循环获取消息,如果存在消息返回,不存在消息或者存在延时消息则永久阻塞等待唤醒或者定时唤醒。
在next()方法中还允许MessageQueue 在队列为null或者存在延时任务的时候  允许执行一些闲时任务。 需要注意的是每次调用next()方法的时候只会执行一次闲时任务(死循环中至会执行一次)。
MessageQueue中还存在着Barrier(阻塞器)  这里面的都是同步阻塞器 ,它会过滤掉之后的同步任务   
同事因为它的存在  移除同步阻塞器的时候(在队首消息队列为null 或者该同步阻塞器为队首Message的时候需要唤醒MessageQueue)  为null唤醒 然后再永久阻塞  不太明白为啥




Looper     Looper的构造方法是私有的  对外提供了一个静态的方法初始化一个Looper  Looper.prepare   它会调用真正的构造方法 初始化一个Looper并绑定当前线程  (需要传入一个Boolean值  用作MessageQueue的初始化 无参构造默认为true  true代表可以退出回收该MessageQueue  false代表无法退出-----一般只有主线程会传入false方法)

Looper的核心方法是loop方法,这个方法必须在Looper.prepare() 之后执行(Looper还没创建和绑定Thread无法执行)  在loop方法中存在一个死循环 它会不断的从消息队列中获取方法进行处理,在这里会发生消息阻塞(消息阻塞是MessageQueue的next方法阻塞),如果消息队列为null,则调处这个死循环

Looper还可以通过调用quit方法退出  ---------具体实现是条用MessageQueue的退出方法,使MessageQueue不再返回消息 loop就退出了。。。




Looper使用示例:
class LooperThread extends Thread {
     public Handler mHandler;
     public void run() {
         Looper.prepare(); //创建并绑定Looper
         //注意构造方法参数
         mHandler = new Handler(Looper.myLooper()) {
             public void handleMessage(Message msg) {
                 //默认情况下哪个线程创建Handler,Handler就会与哪个线程的Looper对象绑定。可以在创建
                 //Handler时指定要与其绑定的Looper。Handler发布的消息会在Handler绑定的Looper中被分
                 //发和处理。
              }
          };
          Looper.loop();//开始消息循环处理
          //消息循环结束后,想要执行的代码段
      }
}



需要注意的是 在这里并没有退出loop死循环的方法,一般的需要我们手动的通知Thread退出   
1.首先因为该子线程处于Looper.loop() 死循环中,不能在该线程中通知退出死循环 只能在其他线程中通知
2.由于在Looper中Looper被ThreadLocal修饰   因此在其他线程中无法获得其他线程的Looper对象  因此只能通过Handler(一定要是和该Looper绑定的Handler)
3.通过Handler获取Looper然后调用Looper的quit()方法 退出死循环

//Handler.getLooper().quit();




Handler   Hanlder是一个收发消息的  工具  
Handler在发送消息的时候主要发送两类   1.Message  2.Runnable      
Message发送的时候采用sendMessage系列的方法发送    Runnable发送的时候使用post系列的方法  
在真正进行信息传递的时候其实都是使用的Message---------MessageQueue只接受Message(Runnable系列被赋值到
了Message的callback上(Message 中的callback其实就是一个Runnable,而且handler在设计的时候 优先执行Message中的callback Runnable))

由此可知  优先执行Message中Runnable的原因是为了处理Handler的Post系列      在其后的处理中  先调用CallBack 接口  如果没有这个接口才会调用handleMessage    

Handler在发送消息后将消息传递给MessageQueue  由MessageQueue对消息进行管理    处理消息的是Looper  在进行处理的时候会执行Message中target(绑定Handler)中的方法进行处理
Hanlder在创建线程的时候 如果不指定Looper会与当前线程的Looper想绑定







Android    Handler  Message   MessageQueue   Looper   异步消息机制   
以子线程更新UI为例:
------------假设当前消息队列为null  主线程Looper是不会推出的,因为MessageQueue当前处于阻塞状态 Looper.loop()方法当前阻塞在了获取Message上

1.在主线程中创建一个Handler(在主线程中创建的Handler会自动绑定主线程Looper,不需要运行Looper.prepare()和当前线程进行绑定)
2.填写消息  传建一个Message对象或者Runnable
3.在子线程中使用在主线程中创建的Handler发送消息(使用Message或者Runnable---------本质上都是需要一个Message对象进行消息传递   Runnable会被赋值给Message的CallBack)
4.发送消息的时候会调用Handler中的MessageQueue 将这条消息加入到消息队列中
5.当消息队列中存在消息后会唤醒MessageQueue,MessageQueue会在给Looper返回一个Message

6.Looper会调用Message中绑定的Handler(Message.target)中的dispatchMessage方法  按照Message.callback//CallBack接口//handleMessage的优先级调用执行方案(这三个方案只会执行一次,此是已经处于主线程中,已经可以进行刷新UI操作)



点击下载源码


0 0
原创粉丝点击