Android-Handler机制详解并自定义Handler

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shangming150/article/details/80814907

之前研究过Android的Handler机制,但是一直没有机会自己实现一次。最近又看到这个Handler机制,于是决定自己实现以下这个Handler机制。
首先,简单介绍以下Handler机制。

Handler机制在Android中通常用来更新UI:子线程执行任务,任务执行完毕后发送消息:Handler.sendMessage(),然后在UI线程Handler.handleMessage()就会调用,执行相应处理。

Handler机制有几个非常重要的类:

Handler:用来发送消息:sendMessage等多个方法,并实现handleMessage()方法处理回调(还可以使用Message或Handler的Callback进行回调处理,具体可以看看源码)。

Message:消息实体,发送的消息即为Message类型。

MessageQueue:消息队列,用于存储消息。发送消息时,消息入队列,然后Looper会从这个MessageQueen取出消息进行处理。

Looper:与线程绑定,不仅仅局限于主线程,绑定的线程用来处理消息。loop()方法是一个死循环,一直从MessageQueen里取出消息进行处理。

原理图如下:
这里写图片描述

按照上面介绍的4个重要组成类,从内向外依次自定义相应的类,实现Handler机制。
MyMessage类

public class MyMessage {
    private int code;
    private String msg;
    MyHandler target;

    public MyMessage(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

MessageQueue类:(由于该类可以有多种实现方式,所以在此定义一个接口)

public interface IMyMessageQueue {
    MyMessage next() throws InterruptedException;
    void enqueueMsg(MyMessage msg) throws InterruptedException;
}

从Android源码中了解到,这个MessageQueue是一个队列,所以在此简单的已一个BlockingQueue队列来实现消息的进队出队操作:

public class MyBlockingQueue implements IMyMessageQueue {
    private BlockingQueue<MyMessage> mQueue;

    public MyBlockingQueue(int init) {
        this.mQueue = new LinkedBlockingDeque<>(init);
    }

    @Override
    public MyMessage next() throws InterruptedException {
        return mQueue.take();
    }

    @Override
    public void enqueueMsg(MyMessage msg) throws InterruptedException {
        mQueue.put(msg);
    }
}

MyLooper类:持有一个MyMessageQueue实例,并使用ThreadLocal绑定当前线程,启动一个死循环。

public class MyLooper {
    private static final ThreadLocal<MyLooper> THREAD_LOCAL = new ThreadLocal<>();
    IMyMessageQueue mMessageQueue;
    private static MyLooper mMainLooper;

    public MyLooper() {
        mMessageQueue = new MyBlockingQueue(4);
    }

    public static void prepare() {
        if (null != THREAD_LOCAL.get()) {
            throw new RuntimeException("Only one looper can be created per thread.");
        }
        THREAD_LOCAL.set(new MyLooper());
    }

    public static void prepareMainLooper() {
        prepare();
        synchronized (MyLooper.class) {
            if (null != mMainLooper) {
                throw new RuntimeException("MainLooper has already been prepared.");
            }
            mMainLooper = myLooper();
        }
    }

    public static void loop() {
        final MyLooper looper = myLooper();
        if (null == looper) {
            throw new RuntimeException("No looper! MyLooper.prepare() wasn't called on this thread.");
        }
        for (; ; ) {
            MyMessage msg = null;
            try {
                msg = looper.mMessageQueue.next();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (null != msg) {
                msg.target.handleMessage(msg);
            }
        }
    }

    public static MyLooper getMainLooper() {
        return mMainLooper;
    }

    public static MyLooper myLooper() {
        return THREAD_LOCAL.get();
    }
}

MyHandler类:持久消息队列,并定义一个抽象方法,负责发送和处理消息。

public abstract class MyHandler {
    private IMyMessageQueue mQueue;

    public MyHandler(MyLooper looper) {
        mQueue = looper.mMessageQueue;
    }

    public MyHandler() {
        MyLooper.myLooper();
    }

    public void sendMessage(MyMessage msg) {
        msg.target = this;
        try {
            mQueue.enqueueMsg(msg);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public abstract void handleMessage(MyMessage msg);
}

到此,自定义Handler功能代码实现,下面测试一下启动MyMainLooper,并在子线程中使用MyHandler发送和处理消息。

TestMyHandler

public class TestMyHandler {

    @Test
    public void test() {
        MainThread mainThread = new MainThread();
        mainThread.start();

        while (null == MyLooper.getMainLooper()) {
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        MyHandler handler = new MyHandler(MyLooper.getMainLooper()) {
            @Override
            public void handleMessage(MyMessage msg) {
                switch (msg.getCode()) {
                    case 1:
                        System.out.print(msg.getMsg() + "在" + Thread.currentThread().getName() + "上执行!\r\n");
                        break;
                    case 2:
                        System.out.print(msg.getMsg() + "在" + Thread.currentThread().getName() + "上执行!\r\n");
                        break;
                }
            }
        };

        new Thread(() -> {
            MyMessage myMessage = new MyMessage(1, "子线程消息1");
            handler.sendMessage(myMessage);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            MyMessage myMessage2 = new MyMessage(2, "子线程消息2");
            handler.sendMessage(myMessage2);
        }).run();
    }

    /**
     * 主线程
     */
    public class MainThread extends Thread {
        public MainThread() {
            setName("MainThread");
        }

        @Override
        public void run() {
            MyLooper.prepareMainLooper();
            System.out.print(getName() + "has been prepared.\r\n");
            MyLooper.loop();
        }
    }
}

测试结果
这里写图片描述

猜你喜欢

转载自blog.csdn.net/shangming150/article/details/80814907