美文网首页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