Android Handler初识

handler机制主要包含的类:

  • Handler :负责发送和接收消息
  • Message :消息承载体
  • MessageQueue :存放消息的队列
  • Looper :开启消息的轮询
为什么要在主线程更新UI?

:系统设计者,为了考虑到用户体验,系统性能

子线程要更新UI,怎么办?

:通过消息机制给主线程发送消息,让主线程更新UI,这个消息机制就是Handler

Handler只能用来更新UI吗?

:Handler其实主要用来线程通信,
也就是可能会出现子线程和子线程通信的情况,那么轮询器Looper初始化就有可能出现在子线程中,
如何保证Looper对象能够在子线程中被正确获取,用于loop轮询呢?答案是ThreadLocal

ThreadLocal是什么?

:ThreadLocal并不是一个Thread,而是Thread的局部变量。 ThreadLocal为解决多线程的并发问题而生。它使变量在每个线程中都有独立拷贝,不会出现一个线程读取变量时而被另一个线程修改的现象。

//这两个方法在哪个线程执行,hander就会在哪个线程接收消息
Looper.prepare();
Looper.loop();
复制代码
重点:

所以Handler不只是为了让子线程去更新UI,hander更重要的作用是可以用来线程间通信,正因为handler可以线程间通信才有了使用handler子线程发消息让主线程更新UI

模拟Hander: 简单手写Hander消息机制加深理解:

public class Message {

    //target储存handerd对象
    Handler target;  
    public int what;
    public Object obj;

    public Message(){ }

    @Override
    public String toString() {
        return obj.toString();
    }
}
复制代码
public class MessageQueue {

    //互斥锁和条件变量
    Lock lock;
    Condition notEmpty;
    Condition notFull;
    Message[] items;

    int putIndex;
    int takeIndex;
    int count;

    public MessageQueue(){
        this.items = new Message[50];
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.notFull = lock.newCondition();
    }

    /**
     * 消息入队,生产者
     * @param message
     */
    public void enqueueMessage(Message message){
        try {
            lock.lock();
            //队列满了,阻塞
            while (count == items.length){
                try {
                    notFull.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //入队
            items[putIndex] = message;
            //循环取值
            putIndex = (++putIndex == items.length) ? 0 : putIndex;
            count++; //元素计数
            //有东西了,通知消费者消费
            notEmpty.signalAll();
        }finally {
            lock.unlock();
        }
    }


    /**
     * 消息出队,消费者
     * @return
     */
    public Message next(){
        Message msg = null;
        try{
            lock.lock();
            while(count == 0){
                try {
                    notEmpty.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            msg = items[takeIndex];
            items[takeIndex] = null;
            //循环取值
            takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
            count--;
            //又有新的空的位置,通知生产者生产
            notFull.signalAll();
        }finally {
            lock.unlock();
        }
        return msg;
    }

}

复制代码
public class Looper {

    static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    MessageQueue mQueue;

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

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

    /**
     * 不断轮询队列中的消息
     */
    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;
            }
            //转发
            msg.target.dispatchMessage(msg);
        }
    }


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

复制代码
public class Handler {

    private Looper mLooper;
    //消息队列
    private MessageQueue mQueue;

    public Handler() {
        mLooper = Looper.myLooper();
        mQueue = mLooper.mQueue;
    }

    /**
     * 发送消息
     * @param msg
     */
    public final void sendMessage(Message msg){
        msg.target = this; //精妙之处,值得回味
        mQueue.enqueueMessage(msg);
    }

    /**
     * 转发消息
     * @param msg
     */
    public void dispatchMessage(Message msg){
        handleMessage(msg);
    }

    /**
     * 处理消息
     * @param msg
     */
    public void handleMessage(Message msg){

    }
复制代码

写个Test类测试下我们刚刚写的Hander机制

public class Test {

    public static void main(String[] args) {

        //线程0:Thread-0
        new Thread(new Runnable() {
            @Override
            public void run() {

                Looper.prepare();

                //在线程0中接受消息
                final Handler handler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        //接收到消息
                        System.out.println(Thread.currentThread().getName() + ",received:"+msg.toString());
                    }
                };

               //线程1:Thread-1 
               //在线程1中发消息
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 5; i++) {
                            Message msg = new Message();
                            msg.what = i;
                            msg.obj = Thread.currentThread().getName() + ",send message:"+ UUID.randomUUID().toString();
                            System.out.println("send:"+msg);
                            handler.sendMessage(msg);
                        }
                    }
                }).start()
                
                Looper.loop();

            }
        }).start();
复制代码

打印语句:可以看到线程1发送的消息 都在线程0中接收到了

send:Thread-1,send message:ecb68c8c-97e9-43ef-8be6-b71f58b731d1
send:Thread-1,send message:1d18184f-4fef-4fdb-8485-b6e336e841c6
Thread-0,received:Thread-1,send message:ecb68c8c-97e9-43ef-8be6-b71f58b731d1
send:Thread-1,send message:9382768d-46f6-4d2b-95d8-c2bdff05b85d
Thread-0,received:Thread-1,send message:1d18184f-4fef-4fdb-8485-b6e336e841c6
Thread-0,received:Thread-1,send message:9382768d-46f6-4d2b-95d8-c2bdff05b85d
send:Thread-1,send message:78451cff-0e4f-4781-bdbd-6ad300f62ab9
send:Thread-1,send message:34536c77-8324-4c59-a179-00ce589de467
Thread-0,received:Thread-1,send message:78451cff-0e4f-4781-bdbd-6ad300f62ab9
Thread-0,received:Thread-1,send message:34536c77-8324-4c59-a179-00ce589de467
复制代码

如果是多个子线程发送消息呢?

public class Test {

    public static void main(String[] args) {

         //线程0:Thread-0
        new Thread(new Runnable() {
            @Override
            public void run() {

                Looper.prepare();

                //线程0:Thread-0 在线程0中接受消息
                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 < 3; i++) {
                    //多个子线程发消息
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < 3; i++) {
                                Message msg = new Message();
                                msg.what = i;
                                msg.obj = Thread.currentThread().getName() + ",send message:"+ UUID.randomUUID().toString();
                                System.out.println("send:"+msg);
                                handler.sendMessage(msg);
                            }
                        }
                    }).start();
                }
                Looper.loop();

            }
        }).start();
    }

}

复制代码

打印语句:可以看到每个线程发送的消息都能在线程0中接收到了

send:Thread-3,send message:40ffbe1c-4234-4d4d-9ace-2433deab14d4
send:Thread-2,send message:f0f38098-86be-431d-962b-6e1029419ff2
send:Thread-1,send message:fe0f68a1-e91c-4840-a6d4-803ab3070e0a
Thread-0,received:Thread-3,send message:40ffbe1c-4234-4d4d-9ace-2433deab14d4
send:Thread-2,send message:a379f356-e9b2-4ccd-84a9-dabc211b826e
send:Thread-3,send message:3dbab897-00b6-4448-a78b-36455dca35aa
Thread-0,received:Thread-2,send message:f0f38098-86be-431d-962b-6e1029419ff2
Thread-0,received:Thread-1,send message:fe0f68a1-e91c-4840-a6d4-803ab3070e0a
send:Thread-3,send message:90446fe2-ecd7-4734-bf79-7a5ae9430c5c
Thread-0,received:Thread-2,send message:a379f356-e9b2-4ccd-84a9-dabc211b826e
Thread-0,received:Thread-3,send message:3dbab897-00b6-4448-a78b-36455dca35aa
Thread-0,received:Thread-3,send message:90446fe2-ecd7-4734-bf79-7a5ae9430c5c
send:Thread-1,send message:667286f0-d73e-4960-97de-37ae01ff3312
send:Thread-2,send message:49643caa-7bf7-4d60-88ca-115118dc9648
Thread-0,received:Thread-1,send message:667286f0-d73e-4960-97de-37ae01ff3312
Thread-0,received:Thread-2,send message:49643caa-7bf7-4d60-88ca-115118dc9648
send:Thread-1,send message:65782fb4-cc21-4366-a976-6c72d6128c2f
Thread-0,received:Thread-1,send message:65782fb4-cc21-4366-a976-6c72d6128c2f
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享