欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handler学习小结

程序员文章站 2022-07-14 17:08:12
...

Handler的消息传递机制

Handler白话理解:Handler是一个消息传递的机制,用来将子线程的数据传递给主线程。

高级用法:实现任意两个线程的数据传递。

1.Handler的引入

Handler类:让新启动的线程周期性地修改UI组件的属性值

常规使用的方式
private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg){
        super.handleMessage(msg);
        switch (msg.what) {
            case MESSAGE_WHAT:
                Log.d(TAG,"main thread receiver message :" + ((String) msg.obj));
                break;
        }
    }
}

private void sendMessageToMainThreadByWorkThread(){
    new Thread(){
        @Override
        public void run(){
            Message message = mHandler.obtainMessage(MESSAGE_WHAT);
            message.obj = "I am message from work thread";
            mHandler.sendMessage(message);
        }
    }.start();
}

白话总结:

1.先创建一个Handler(在主线程里)

2.重写Handler里面的handlerMessage方法,方法传入一个参数Message,其他线程传过来的信息就是这个。

3.子线程是怎么传递信息的呢,先通过.obtainMessage方法,获取一个Message的实例

补充:

Message.what => 用来标识信息的int值,通过该值主线程能判断出来自不同地方的信息来源。

Message.arg1/Message.arg2 => Message初始定义的用来传递int类型的两个变量。

Message.obj => 用来传递任何实例化对象。

sendMessage将Message发送出去。

两个子线程之间的通信

在一个线程创建Handler,另外一个线程通过持有该Handler的引用调用sendMessage发送消息。

private Handler handler;

private void handlerDemoByTwoWorkThread(){
    Thread hanMeiMeiThread = new Thread(){
        @Override
        public void run(){
            // Looper.prepare();
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg){
                    Log.d(TAG,"hanMeiMei receiver message:" + ((String) msg.obj));
                    Toast.makeText(MainActivity.this,((String) msg.obj),Toast.LENGTH_SHORT).show();
                }
            };
            //Looper.loop();
        }
    };
    
    Thread liLeiThread = new Thread(){
        @Override
        public void run() {
            try{
                Thread.sleep(2000);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            Message message = handler.obtainMessage();
            message.obj = "Hi MeiMei";
            handler.sendMessage(message);
        }
    };
    hanMeiMeiThread.setName("韩梅梅 Thread");
    hanMeiMeiThread.start();
    liLeiThread.setName("李雷 Thread");
    liLeiThread.start();
}

2.Handler的执行流程

引入—Handler、Looper、Message这三者与异步消息处理线程

知识点一:异步消息处理线程启动后会进入一个无限的循环体中,每循环依次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环。若消息队列为空,线程则会阻塞等待。

知识点二:那么Android消息机制主要是指Handler的运行机制,Handler运行需要底层的MessageQueue和Looper支撑,其中MessageQueue采用的是单链表的结构,Looper可以叫做消息循环。由于MessageQueue只是一个消息存储单元,不能去处理消息,而Looper就是专门处理消息的,Loopr会以无限循环的形式去查找是否有新消息,如果有的话,就处理,否则就一直等待着。

知识点三:我们知道,Handler创建的时候会采用当前线程的Looper来构造消息循环系统,需要注意的是,线程默认是没有Looper的,如果需要使用Handler就必须为线程创建Looper,因为默认的UI主线程,也就是ActivityThread,ActivityThread被创建的时候就会初始化Looper,这也是在主线程中默认可以使用Handler的原因。

解析:

⭐️Message:Handler接收和处理的消息对象

1.2个整型数值:轻量级存储int类型的数据。

2.1个Object:任意对象。

3.reply To:线程通信时使用。

4.what:用户自定义的消息码,让接收者识别消息。

⭐️MessageQueue:Message的队列

1.采用先进先出的方式管理Message。

2.每个线程最多可以拥有一个。

⭐️Looper:消息泵,是MessageQueue的管理者,会不断从MessageQueue中取出消息,并将消息分给对应的Handler处理

1.每个线程只有一个Looper。

2.Looper.prepare():为当前线程创建Looper对象

3.Looper.myLooper():可以获得当前线程的Looper对象。

4.Handler:能把消息发送给MessageQueue,并负责处理Looper分给它的消息。

3.Handler的相关方法

????void handleMessage(Message msg):处理消息的方法。该方法通常用于被重写。

????final boolean hasMessages(int what):检查消息队列中是否包含what属性为指定值的消息。

????finalboolean hasMessages(int what,Object object):检查消息队列中是否包含what属性为指定值且object属性为指定对象的消息

????多个重载的Message obtainMessage():获取消息

????sendEmptyMessage(int what):发送空消息

????final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定多少毫秒后发送空消息

????final boolean sendMessage(Message msg):立即发送消息

????final boolean sendMessageDelayed(Message msg,long delayMillis):指定多少毫秒后发送消息

4.Handler的使用


如果写在主线程不需要Looper对象

Handler写在子线程中,则需自己创建一个Looper对象


总结:

1.在使用handler的时候,在handler所创建的线程需要维护一个唯一的Looper对象,每个线程对应一个Looper,每个线程的Looper通过ThreadLocal来保证,Looper对象的内部又维护有唯一的一个MessageQueue,所以一个线程可以有多个handler,但是只能有一个Looper和一个MessageQueue。

2.Message在MessageqQueue不是通过一个列表来存储的,而是将传入的Message存入到了上一个Message的next中,在取出的时候通过顶部的Message就能按放入的顺序依次取出Message。

3.Looper对象通过loop()方法开启了一个死循环,不断地从looper内的MessageQueue中取出Message,然后通过handler将消息分发传回handler所在的线程。


本文部分内容参考:

Android Handler详解 - 简书 (jianshu.com)