从源码层下手,实现Handler核心机制

Android 高级工程师进阶 ~ 网易云课堂 学习笔记

【课程主题】Handler源码分析 - 手把手带你实现Handler机制核心架构

【课程大纲】

1.Handler源码分析

2.根据源码手写实现Handler核心机制

3.充分理解Handler机制的作用

戳此链接加入学习:https://url.163.com/Ngk

Handler源码分析

1,什么是 Handler

Android SDK 中用来处理异步消息的核心类

子线程可以通过Handler 来通知主线程进行UI更新

Handler 机制核心类

Handler

Looper
轮询器 ,不断去消息队列中查询消息 发生到 线程中去

Message
在整个消息处理机制中,Message 又叫 Task ,封装了任务携带的信息和处理该任务的Handler,有这么几点需要注意:
(1)尽管Message 有 Public的默认构造方法,但是你应该通过Message.obtain() 来从消息中获得空消息对象,以节省资源。

(2) Message如果只需要携带 简单的 int 信息 ,请优先 使用 arg1 和 arg2 来传递消息,这比使用 Bundle 更省内存。

MessageQueue
消息队列

在这里插入图片描述
在这里插入图片描述
入队
Handler.sendMessage -> queue.enqueueMessage

出队
Looper.loop -> queue.next

Handler

MessageQueue mQueue
Looper mLooper

ThreadLocal 线程的数据隔离

根据源码手写实现Handler核心机制

直接撸代码

1, Handler 类

package com.example.handlerlib;

public class Handler {

    private MessageQueue mQueue;
    private Looper mLooper;

    public Handler() {
        //获取主线程的Looper对象
        mLooper = Looper.myLooper();
        this.mQueue = mLooper.mQueue;
    }

    /**
     * 发生消息,压人队列
     */
    public void sendMessage(Message msg) {
        msg.target = this;//将Handler 绑定到msg 的 target
        mQueue.enqueueMessage(msg);
    }

    public void handleMessage(Message msg) {

    }

    public void dispatchMessage(Message msg) {
        handleMessage(msg);
    }
}

2,Looper 类

package com.example.handlerlib;

public final class Looper {

    /**
     * 每一个主线程都会有一个Looper对象
     * Looper对象 保存在ThreadLocal,保证子线程数据隔离
     */
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();

    // 有一个对应的消息队列
    MessageQueue mQueue;

    private Looper() {
        mQueue = new MessageQueue();
    }

    /**
     * Looper 对象的初始化
     */
    public static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }


    /**
     * 获取当前Looper对象
     *
     * @return
     */
    public static Looper myLooper() {
        return sThreadLocal.get();
    }

    /**
     * 轮询消息队列
     */
    public static void loop() {

        Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread");
        }
        MessageQueue queue = me.mQueue;
        for (;;){
            Message msg = queue.next();
            if (msg == null){
                continue;
            }

            // 转发给Target  即Handler
            msg.target.dispatchMessage(msg);
        }
    }


}

3,Message 类

package com.example.handlerlib;

public class Message {
    Handler target;
    public int what;
    public Object obj;

    @Override
    public String toString() {
        return obj.toString();
    }
}

4,MessageQueue 类

package com.example.handlerlib;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MessageQueue {

    // 通过数组的结构存储 Message 对象
    Message[] items;

    //入队与出队的元素的索引位置
    int putIndex;
    int takeIndex;

    //计数器
    int count;

    private Lock lock;
    //条件变量
    private Condition notEmpty;
    private Condition notFull;


    public MessageQueue() {
        //消息队列应该有大小限制
        this.items = new Message[50];
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.notFull = lock.newCondition();
    }

    /**
     * 加入队列
     *
     * @param msg
     */
    public void enqueueMessage(Message msg) {
        try {
            lock.lock();
            //消息队列满了,子线程停止发送消息 阻塞
            while (count == items.length) {
                try {
                    notFull.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            items[putIndex] = msg;
            //循环取值
            putIndex = (++putIndex == items.length) ? 0 : putIndex;
            count++;
            //有新的Message 对象,通知主线程
            notEmpty.signalAll();
        } finally {
            lock.unlock();
        }

    }

    /**
     * 出队
     *
     * @return
     */
    public Message next() {
        Message msg = null;
        try {
            lock.lock();
            //如果消息队列是空的,,主线程looper 停止轮询
            while (count == 0){
                try {
                    notEmpty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            msg = items[takeIndex];//取出
            items[takeIndex] = null;//元素置空
            //循环取值
            takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
            count--;
            //使用了一个Message 对象,继续生产
            notFull.signalAll();
        } finally {
            lock.unlock();
        }


        return msg;
    }
}

5,测试类

package com.example.handlerlib;

import java.util.UUID;

public class HandlerTest {
    public static void main(String[] args) {

        // 轮询器初始化
        Looper.prepare();
        final Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                System.out.println(Thread.currentThread().getName() + ",received:" + msg.toString());
            }
        };

        // 子线程发生消息
        for (int i = 0; i < 10; i++) {
            new Thread() {
                @Override
                public void run() {
                    while (true) {
                        Message message = new Message();
                        message.what = 1;
                        synchronized (UUID.class){
                            message.obj = Thread.currentThread().getName() + " ,send Message:" + UUID.randomUUID().toString();
                        }
                        System.out.println(message);
                        handler.sendMessage(message);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }.start();
        }
        Looper.loop();


    }
}

源码地址
https://github.com/yoyo0316/StudyDemo/commit/23b2583ccf276554f83100d5aa62dafecffc9766

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值