美文网首页Android技术知识Android开发
自己动手实现Handler消息机制

自己动手实现Handler消息机制

作者: 猫叔很不爽 | 来源:发表于2020-03-13 11:38 被阅读0次

缓缓飘落的枫叶像思念

当弄明白了Handler机制实现的原理后,自己动手实现一下消息在线程间切换是很简单的事情。

首先我们先来明确一下Handler机制中需要用到的类

  1. Handler类。Handler类负责关联当前线程的Looper和MessageQueue,以及发送消息到MessageQueue中,还有一个消息处理的回调。
public class MyHandler {

    private MyMessageQueue messageQueue;

    // 获取Looper与消息队列
    public MyHandler(){
        MyLooper myLooper = MyLooper.myLooper();
        messageQueue = myLooper.getMessageQueue();
    }

    // 分发消息
    public void dispatchMessage(MyMessage msg){
        handleMessage(msg);
    }

    // 发送消息
    public void sendMessage(MyMessage message) {
        // 将当前的Handler对象赋值给了message的target,
        message.target = this;
        messageQueue.addMessage(message);
    }

    public void handleMessage(MyMessage msg) { }
}
  1. Looper有两个最主要的方法,prepare()和loop()。prepare()方法创建了一个Looper对象,并存入ThreadLocal对象中。loop()从消息队列中不停的取出Message,通过Message.target回调给处理的Handler。此外,Looper还创建了MessageQueue,以及MessageQueue的获取方式。
public class MyLooper {

    private static ThreadLocal<MyLooper> threadLocal = new ThreadLocal<>();
    public static  MyMessageQueue messageQueue;

    private MyLooper(){
        messageQueue = new MyMessageQueue();
    }

    public MyMessageQueue getMessageQueue(){
        return messageQueue;
    }

    /**
     * 获取当前线程的looper
     */
    public static MyLooper myLooper(){
        MyLooper myLooper = threadLocal.get();
        return myLooper;
    }

    // 给当前线程创建一个相关联的Looper对象,并存在ThreadLocal当中
    public static void prepare(){
        if(threadLocal.get() != null){
            throw new RuntimeException("Current Thread is created looper");
        }else{
            threadLocal.set(new MyLooper());
        }
    }
    
    public static void loop(){
        MyLooper myLooper = threadLocal.get();
        while(true){
            List<MyMessage> msgList = myLooper.messageQueue.getMsgList();
            for(int i = 0; i < msgList.size(); i++){
                MyMessage myMessage = msgList.get(i);
                myMessage.target.dispatchMessage(myMessage);
                msgList.remove(msgList.get(i));
            }
        }
    }
}
  1. Message类就很简单了。只有一个Handler类型的引用,然后what和存储数据的obj。
public class MyMessage {

    public  MyHandler target;

    public int what;

    public Object obj;

}
  1. MessageQueue中也只是维护了一个队列。、
public class MyMessageQueue {

    private List<MyMessage> msgList = new ArrayList<MyMessage>();

    public void addMessage(MyMessage msg){
        msgList.add(msg);
    }

    public List<MyMessage> getMsgList(){
        return msgList;
    }
}
  1. 测试
public class MainActivity extends AppCompatActivity {

    private MyHandler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                MyLooper.prepare();
                mHandler = new MyHandler(){
                    @Override
                    public void handleMessage(@NonNull MyMessage msg) {
                        if(msg.what == 0x111){
                            Log.e("thread1",msg.obj.toString() );
                        }
                    }
                };
                MyLooper.loop();
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                    MyMessage message = new MyMessage();
                    message.what = 0x111;
                    message.obj = "哎呀妈呀,都特么开始手写Handler了,牛逼牛逼!";
                    mHandler.sendMessage(message);
                    try{
                        Thread.sleep(2000);
                    }catch (Exception ee){
                        ee.printStackTrace();
                    }
            }
        });
        thread1.start();
        try{
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
        thread2.start();
    }
}
image.png

测试后,可以看到消息确实是从thread2发送给了thread1。手写Handler完美成功。
但是我们这里有一个问题,就是Thread1收到一次消息后,如果再在Thread2里面发送一次消息,Thread1就收不到消息了。因为Thread1的线程已经执行完了,Handler对象也就被销毁了。
我们平常用的Handler都是接收了一个消息之后,还是可以继续接收的。因为我们创建Handler的时候是在主线程创建的,而主线程是一直运行的,不会死掉的,直到我们退出APP。

武汉还是没有解封,今年凉凉。没得工作。前途茫茫。

相关文章

网友评论

    本文标题:自己动手实现Handler消息机制

    本文链接:https://www.haomeiwen.com/subject/hgcqshtx.html