面试题之--Handler-消息机制

一,作用:是用来做异步的,用于在子线程更新UI

,关键类的详细介绍

1,概念介绍

Message

· 定义:消息,理解为线程间通讯的数据单元(Handler接受和处理的消息对象。)

例如后台线程在处理数据完毕后需要更新UI,则可发送一条包含更新信息的Message给UI线程

Message Queue

扫描二维码关注公众号,回复: 3368263 查看本文章

· 定义:消息队列

· 作用:用来存放通过Handler发过来的消息,按照先进先出执行

Handler

· 定义:Handler是Message的主要处理

.作用:负责将Message添加到消息队列&处理Looper分派过来的Message

Looper

定义:循环器,扮演Message Queue和Handler之间桥梁的角色

作用:主要负责消息循环:循环取出Message Queue的Message;消息派发:将取出的Message交付给相应的Handler

一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue

2,相关方法介绍

Handler

· 提供sendMessage方法,将消息放置到队列中

· 提供handleMessage方法,定义个各种消息的处理方式;

Looper

· Looper.prepare():实例化Looper对象;为当前线程生成一个消息队列;

· Looper.loop() :循环从消息队列中获取消息,交给Handler处理;此时线程处于无限循环中,不停的从MessageQueue中获取Message 消息 ;如果没有消息就阻塞

MessageQueue

· 提供enqueueMessage 方法,将消息根据时间放置到队列中;

· 提供next方法,从队列中获取消息,没有消息的时候阻塞;

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case 1:
                Log.e("date","接收到传递的信息了" );
                break;
        }
        super.handleMessage(msg);
    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {
        @Override
        public void run() {
            Message msg = Message.obtain();
            msg.what = 1;
            mHandler.sendMessage(msg);
        }
    }).start();
}

三,实现原理:

  每当创建一个handler的时候,就会创建一个MessageQueue来存储消息,接着创建Lopper循环器,在Messagequeue队列里不停的轮训,看看有没有消息,没有消息就一直轮训,当Handler拿到消息,就会通过sendMessage()方法,将message从子线程发送出去,这个时候looper轮训到有消息来,就会将传递出去,传递到handler的handlerMessage()方法中,这个时候就可以在UI线程刷新数据了.

  这个MessageQueue队列的结构其实并不是队列,而是采用单链表的数据结构来维护消息队列,因为单链表的数据结构在插入和删除上比较有优势.

     Handler一般只能只在主线程创建对象,如果在子线程创建对象,会报错,(has not called Looper.prepare())因为Handler工作需要Looper,没有lopper就会报错.在主线程内部自带的调用了Lopper.prepare()方法创建Lopper对象.如果想要在子线程创建对象,就必须自己调用prepare()方法,如果想在子线程接收消息,还得调用Looper.loop()方法不停轮询,才能收到消息.但在事情结束后,要调用quit()来终止消息循环,否则线程就会处于一直等到状态

 

3,其他重要的类:

ThreadLocal,它是一个可以在指定线程中存储数据的类,数据存储以后,只有在指定的线程中可以获取到存储的数据,在其他线程无法获取该数据,ActivityThread,ActivityManagerService就用到了就用到了ThreadLocal.

4,不同线程有不同的lopper

 

四,源码

1,自身的创建&创建Message Queue:prepare()方法

五,Handler造成的内存泄漏,

         1,handler造成内存泄漏是因为在Activity销毁的时候还有未执行完的任务

         2,解决方法:
                2.1,静态static可以解决内存泄漏
                2.2,使用弱引用也可以解决内存泄漏,但是需要等到handler的中任务都执行完,才会释放activity内存,不如直接static释放的快

               2.3,  handler.removeCallbacksAndMessages(null);

         3,handler造成内存泄漏有 两种方案:一种是业务逻辑上,在activity销毁的时候移除所有未执行的任务。一种是从GC上,通过static的Handler或者弱引用解决。但是单独的使用弱引用性能不是太高。

handler内存泄漏解决方式

借鉴:

Android开发:Handler异步通信机制全面解析(包含Looper、Message Queue)

 

https://www.jianshu.com/p/9fe944ee02f7

猜你喜欢

转载自blog.csdn.net/qq_38859786/article/details/79539907