Looper类和Handler类小结

Looper类和Handler类分析

工作原理

  • 有一个消息队列,可以往这个消息队列中投递消息
  • 有一个消息循环,不断从消息队列中取出消息,然后处理.
  1. 事件源添加待处理的消息,一般是在队尾添加如果有优先级高的消息,按照优先级越高位置越靠前.
  2. 事件源提交消息:通过 按键,触屏 等物理时间产生,也可以是 系统或应用 本身发出的请求

Looper类
class LooperThread extends Thread{
        @Override
        public void run() {
            super.run();
            //调用prepare
            Looper.prepare();
            //进入消息循环
            Looper.loop();
        }
    }

关键两步(1)Looper.prepare();

private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

prdepare函数主要做一个事情
在调用prepare的线程中,设置了一个Looper对象,这个Looper对象保存在这个调用线程的TLV中,Looper对象内部封装了一个消息队列
也就是说,prepare函数通过ThreadLocal机制,巧妙的把Looper和调用线程关联在一起.

(2)Looper.loop();


     public static void loop() {
     //关键代码
        final Looper me = myLooper();
        mThread = Thread.currentThread();
    }

Looper的作用是:
1.封装了一个消息队列
2. Looper的prepare函数把这个Looper和调用prepare的线程(最终的处理线程)绑定在一个.
3. 处理线程调用了loop函数,处理来自该消息队列的消息.
[总结]
Looper有一个Message队列,里边储存的是一个个待处理的message
Message中有一个Handler,这个Handler是用来处理Message的

Handler分析

包含成员

  1. MessageQueue
  2. Looper
  3. Callback

在不使用Handler的情况下,插入消息需要:

1. 调用Looper的myQueue,它返回一个MessgeQueue
2. 构造一个Message 填充它的成员,尤其是target变量.
3. 调用mesaageQueue的enqueueMessage,将消息插入队列  

这种原始方法很麻烦,也容易出错,下面看看有了Handler以后我们的工作得到了那些优化:


    //查看队列中是否有消息
    public final boolean hasMessages(int what)
    //从handler中创建一个消息
    public final Message obtainMessage()
    //从消息队列中移除消息
    public final void removeCallbacks(Runnable r)
    //发送一个消息,该消息添加到队列头--优先级最高
    public final boolean sendEmptyMessageAtTime
                    .
                    .
                    .

Handler 把Message的target设置为自己,因为Handler除了封装消息添加等功能外,还封装了消息处理的接口.

Looper 在获得消息后会调用target.dispatchMessage函数,再把这个消息派发给Handler处理.

  • dispatchMessage 定义了一套消息处理的优先级机制如下:
  1. Message自带了callback 处理,则交给callback处理
  2. Handler如果设置了全局的mCallback,则交给callback处理.
  3. 如果上述都没有,该消息则会被交给Handler子类实现的handleMessage来主城里(需要Handler培生并重载handleMessage函数)
    通常情况下,我们一旦都是采用第三种方法–在子类中通过重载handleMessage来完成处理工作.

拓展
HandlerThread

测试场景
主线程有耗时操作,同时需要handlemessage接受一些更新操作,这是需要再开启一个线程


         //开启子线程2
        handlerThread = new HandlerThread("handler_Thread");
        //运行子线程
        handlerThread.start();
        /**
        *子线程与handler 进行关联 注:此处getLooper不可以使用Looper.getLooper(获取当前线程的looper即主线程looper)
        **/
        handler = new Handler(handlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.e("handler=====", msg.getTarget().getLooper().getThread().getName());
                handlerMain.sendEmptyMessage(1);
            }
        };
        //主线程
        handlerMain = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.e("handler=====", msg.getTarget().getLooper().getThread().getName());
                handlerThread.quit();
                handler.removeCallbacksAndMessages(null);
            }
        };
    //UI耗时操作
    private void initUI() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    handler.sendEmptyMessage(1);
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }

运行结果: handler_Thread 立即触发
main 被阻塞延时5秒

  • [参考文献] 深入理解Android卷I
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值