Handler源码解析及相关问题

Handler机制相关概念

  • Handler
    发送和处理消息。
  • Looper
    循环从消息队列取数据。
  • Runnable和Message
    任务和消息,任务最终也会转化成message。
  • MessageQueue
    消息队列,存储消息数据。

Handler机制流程及源码分析

Android开发中案例中,经常在子线程产生的数据发送到主线线程进行处理。处理流程类似于生产者-消费者,子线程(生产者)和消费者(主线程)同个时间段公用存储空间(Message)。

    private static Handler mHandler = new Handler(new Handler.Callback() {
   
   
        @Override
        public boolean handleMessage(@NonNull Message msg) {
   
   
            //处理消息
            return false;
        }
    });
        //发送消息
        mHandler.sendEmptyMessage(0);
        mHandler.post(new Runnable() {
   
   
            @Override
            public void run() {
   
   

            }
        });

在这里插入图片描述

流程及源码分析

创建Looper

主线程创建,在主线程即UI线程ActivityThread启动时(main函数)就通过Looper.prepareMainLooper()创建了。

//frameworks\base\core\java\android\app\ActivityThread.java
public static void main(String[] args) {
   
   
    ...
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
   
   
        sMainThreadHandler = thread.getHandler();
    }
    Looper.loop();
}
//frameworks\base\core\java\android\os\Looper.java
    public static void prepareMainLooper() {
   
   
        prepare(false);//主线程不能quit
        synchronized (Looper.class) {
   
   
            if (sMainLooper != null) {
   
   
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

子线程创建需要调用Looper.prepare()

//frameworks\base\core\java\android\os\Looper.java
//sThreadLocal是静态且不可变的,唯一
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    public static void prepare() {
   
   
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
   
   
        //创建前先判断当前线程是否不为空,不为空表示Looper已经创建,保证一个线程只有一个Looper
        if (sThreadLocal.get() != null) {
   
   
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //创建Looper并保存到ThreadLocal中
        sThreadLocal.set(new Looper(quitAllowed));
    }
//libcore\ojluni\src\main\java\java\lang\ThreadLocal.java
    public void set(T value) {
   
   
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
           //实际是将Looper保存到对应线程里的map,键值是sThreadLocal
            map.set(this, value);
        else
            createMap(t, value);
    }
创建MessageQueue

MessageQueue是一个消息队列,会有队列的一些操作方法。

  • 新建队列
    在创建Looper的时候会创建一个MessageQueue,一个线程对应一个MessageQueue。由其构造函数和本地方法nativeInit组成,nativeInit会在本地创建一个NativeMessageQueue对象。
    private Looper(boolean quitAllowed) {
   
   
        mQueue = new MessageQueue(quitAllowed);
        //和当前线程绑定
        mThread = Thread.currentThread();
    }

    MessageQueue(boolean quitAllowed) {
   
   
       //是否允许quit,主线程是flase,不允许队列销毁退出。
        mQuitAllowed = quitAllowed;
        mPtr = nativeInit();
    }
  • 元素入队
    boolean enqueueMessage(Message msg, long when)
  • 元素出队
    Message next()
  • 删除元素
    void removeMessages(Handler h, Runnable r, Object object)
    void removeMessages(Handler h, int what, Object object)
  • 销毁队列
    和创建过程一样通过本地方法nativeDestroy
Looper.loop()循环
    public static void loop() {
   
   
        final Looper me = myLooper();//通过sThreadLocal.get()获取刚才创建的Looper
        if (me == null) {
   
   
            throw new RuntimeException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值