Android 我的复习资料19.Handler

Handler 消息机制

    当我们创建一个Handler 的时候,会和一个默认的线程进行绑定,这个默认线程中会有一个
MessageQueue(消息队列).
    作用1:定时的去发送一个Message  / runnable对象
    作用2:我么可以在一个子线程中进行消息发送在HandleMessage更新UI
    
    创建应用时,会默认创建一个UI线程,UI线程默认创建一个Looper,主线程主要是运行一个MessageQueue管理
一些大组件比如Acticity,BroadCastReceiver
    
一.Handler封装了消息的发送 (主要包括消息发送给谁)
    Looper
    1.内部包含一个消息队列也就是MessageQueue,所有的Handler发送的消息都走向这个消息队列
    2.Looper.Looper()方法,就是一个死循环,不断的从MessageQueue取消息,如果有消息就处理消息,没有消息
     就阻塞线程
二.MessageQueue,就是一个消息队列,可以添加消息,并处理消息

三.Handler内部会跟Looper进行关联,也就是说Handler的内部可以找到Looper,找到Looper也就是找到了
    MessageQueue,在Handler中发送消息就是向MessageQueue中发送消息
    
总结:handler 负责发送消息,Loopeer负责接收Handler发送的消息,并直接把消息回传给Handler自己.
    MessageQueue就是一个存储消息的容器
    
    ActivityThread 默认创建一个Main 默认创建一个Looper 创建Looper时会默认创建一个MessageQueue
    在ActivityThread中 ,会首先调用Looper.preparMainLooper()
    ThreadLocal 保存线程变量
    ThreadLocal set get 有looper抛出异常只能有一个  默认为空 Looper构造方法中会先new
    一个MessageQueue  
    
    handler  Loop.myLooper  返回 一个从ThreadLocal中取出来的Looper 变量
    mlooper.mQueue 拿到MessageQueue
    sendMessageDelay  sendMessageAtTime(Message msg,long dalayMills)  
    dalayMills(就是得到系统当前时间+设置的延迟时间)
    最后把消息放进消息队列中 queue.enqueueMessage(msg,uptimeMills)
    添加是会有很多环节 比如 会有判断当前msg.target也就是Handler是否存在  当前消息是否已经被使用
       然后是当前线程是够已经退出 死亡  
       然后才进行添加的操作,并且打上标识已经在使用的标识 msg.markInUse();
       最后添加进MessageQueue队列
Looper的轮询   主要是通过Looper.loop方法进行轮询在Loop方法中首先使用myLooper()
也就是从ThreadLocal中拿出来looper的变量 取出消息队列 通过死循环  不停的调用queue.next从中去除消息Message 如果消息为空就return 阻塞
不为空就调用msg.target.dispatchMessage方法  也就是调用Handler自己的方法  
在这个如果我们没有写callBack 并且返回一个true 进行一个拦截 name直接回调 handleMessage方法
进行消息的处理
    
    
    子线程更新UI的几种方式:
    Handler.post
    Handler.sendMessage
    View.Post
    runOnUiThread()
    
    当我们view.settext时,会调用checkForRelayout --->invalidate--> p.invalidateChild(this,damage)
    --->invalidateChildInparent()-->checkThread() 会判断  nThread与Thread.currentThread  
    不是的话就抛出异常 常见的那个必须在主线程跟新UI  
    checkThread() 这个方法是在viewrootimpl 中的  他是在onResume中创建的
    
    viewrootimpl里判断当前View 的线程是否与主线成一致  不是就抛出异常
    viewrootimpl在onResume中创建的 所以我们第一次没有休眠时他还没有进行判断
    走了这个HandlerResumeActivity方法.
    
    在ActivityThrad中,有一个HandlerResumeActivity方法, getDecorView 最里层的一个布局帧布局
还有ViewManager一个接口进行管理View  ,其中有AddView,其中调用了这个AddView  最后可以看到他
初始化了viewrootimpl.

 

Android 我的复习资料19.Handler