Handler的原理-----源码剖析

1. handler是什么?

Handler是android给我们提供的用来更新UI的一套机制,也是一套消息处理机制,我们可以发送消息,也可以通过它处理消息。

2. 为什么要用handler?

Android在设计时就封装了一套消息创建,传递,处理机制。如果不遵循这样的机制,就没办法更新UI信息,就会抛异常。

3. handler如何使用?

sendMessage();
sendMessageDelay();
post(Runnable);
postDelay(Runnable, long);
//前两个方法一般用于耗时性操作后的更新UI。
//后两个方法可以用来完成周期性的任务,如视频播放器进度条一秒跑一下....
.........

4. Android中Message的生成方式

Message msg = new Message();
Message msg = Message.obtain();

5. 初始化一个Handler对象

Handler handler = new Handler(){
    Void handlerMessage(Message msg){}
    //接受子线程发来的消息,在主线程中进行处理
    //不会有ANR,不会在子线程中更新UI
}

6. Handler的构造函数中初始化Looper(轮询器),MessageQueue(消息队列).

Public Handler(CallBack callBack){
    …
    mLooper = Looper.myLooper();
    …
    mQueue = mLooper.mQueue();
    mCallback = callback;
}

7. Looper在ActivityThread的main函数中初始化:

Public static final void main(String[] args){
    //初始化Looper
    Looper.prepareMainLooper();
    Looper.loop();
}

8. Looper进行消息队列的循环,可能导致阻塞,但是界面不卡(原因:管道pipe)。

Pipe是linux下的一个特殊的文件,是一种linux的线程通讯机制。只存在在内存中。拥有两个描述符(对文件操作的句柄,其实就是引用),一个是用来写入,一个用来读取。
应用场景:一个主线程拿着读取描述符,等待读取。子线程拿着写入的描述符,将数据写入管道,发出通知,主线程开始读取,实现不同线程之间的通讯问题。
Handler的应用场景:handler拿着读取描述符,阻塞主线程(睡眠),等待读取。子线程通过handler的sendMessage()将一个Message放入MessageQueue消息队列中,通知主线程,主线程开始轮询。

9. Loop中的循环代码

Public static final void loop(){
    Looper me = myLooper();
    MessageQueue queue = me.mQueue();
    While(true){
        //死循环,不断去消息队列中的数据。
        //如果没有消息,则睡眠等待。
        Message msg = queue.next(); //might block
    }
}

10. Handler的sendMessage(),消息的转发。

Public final Boolean sendMessage(Message msg){
    //第一次转发
    Return snedMessageDelayed(msg,0);
}
Public final Boolean send snedMessageDelayed(Message msg, long delayMillis){
    //第二次转发
    If(delayMillis < 0){
    delayMillis = 0;
    }
    Return sendMessageAtTime(msg, SystemClock.upTimeMillis() +delayMillis);
}
public Boolean sendMessageAtTime(Message msg, long upTimeMillis){
    Boolean sent = false;
    MessageQueue queue = mQueue;
    If(queue != null){
        //把当前的Handler对象的引用交给Message的target对象
        Msg.target = this;
        //把消息放入MessageQueue
        Sent = queue.enqueueMessage(msg, upTimeMillis);
    }   
    Return sent;
}

11. 在loop中如果收到消息,next拿到Message,通过handler.dispatch()进行分发。

Public static final void loop(){
    Looper me = myLooper();
    MessageQueue queue = me.mQueue();
    While(true){
        //死循环,不断去消息队列中的数据。
        //如果没有消息,则睡眠等待。
        Message msg = queue.next();     //might block
        msg .target.dispatchMessage();      //如果拿到了消息,则进行分发
    }
}

12. 进入到handler进行消息的转发处理

Public void dispatchMessage(Message msg){
    handlerMessage(msg);

}

13. 子类实现handlerMessage()方法。

public void handlerMessage(Message msg){
    switch(msg.what){
        .......
    }
}

总结:

第5步和第13步是我们在代码中写的,其余的系统自动完成。
  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 2

打赏作者

安卓_lover

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值