Handler,MessageQueue,Runnable,Message与Looper

本文深入探讨了Android中的Handler、MessageQueue、Runnable、Message和Looper之间的关系及其工作原理。通过这些组件,开发者可以实现UI线程与其他线程之间的通信,处理异步消息并更新用户界面。
摘要由CSDN通过智能技术生成
1.Runnable和Message可以被压入到MessageQueue中,形成一个集合。一般情况下某种类型的MessageQueue只允许保存相同类型的Object,实际源码中需要先对Runable进行相应转换。
2.Looper循环的去从MessageQueue中取出item,然后交与Handler处理。加入消息队列为空,Looper将进入休眠。

3.Handler利用自身的处理机制,对传入的各种Object进行处理并产生最终效果。

Handler

    每一个Thread只对应一个Looper;
    每一个Looper只对应一个MessageQueue;
    每一个MessageQueue中有N个Message;
    每一个Message最多只能由一个Handler来处理。
由此,Thread和Handler是一对多的关系。
Handler的工作:
~1.处理Message,包括对Message进行分发,和对Message进行处理。
分发流程,首先判断msg.callback是否为空,在Message类中,可以知道msg.callback就是Runable,不为空优先处理,即执行run方法;其次判断Handler.mCallback是否为空,不为空时调用mCallback.handlerMessage;如果前两个对象都不存在,才调用Handler.handlerMessage
~2.将某个Message压入MessageQueue中。post系列的方法都是提供的Runnable对象,post需要先将其封装成Message,接着通过对应的send函数把它推送到MessageQueue中。这里需要注意可以将消息至于消息队列的最前端,即looper优先取出。
~3.将某个Message从MessageQueue中移除。可以移除尚未被执行的Runnable。
Looper

    Looper在Android线程中使用只有三个步骤:
    1.Looper的准备工作(prepare)
    2.创建处理消息的Handler
    3.Looper开始工作(loop)
Looper在应用程序中的使用分为两种情况
    1.主线程
    2.普通线程

    在 ActivityThread.java 源码中的main方法里面有下面一段代码:
Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        AsyncTask.init();
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Looper.loop();

其中 Looper.prepareMainLooper()和Looper.prepare()本质上有没有区别?
Looper.prepareMainLooper()的代码:
public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

Looper.prepare()的代码:
public static void prepare() {
        prepare(true);
    }
    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));
    }
我们可以看到都用到了prepare,参数中的false表示线程不允许退出。所以说在本质上两者是没有什么区别的。
sThreadLocal.get()是什么呢?
在Looper中有一个很重要的成员变量:
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
这是一个静态类型的变量,只要import了Looper, sThreadLocal  就会存在并构建完毕。
ThreadLocal是什么东西呢?
Implements a thread-local storage, that is, a variable for which each thread has its own value.
由此, ThreadLocal是一中特殊的全局变量,全局性只限于自己的线程, sThreadLocal.get()  告诉我们,每个线程的Looper都是独立的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值