Android学习日记

Android日记之消息机制(1)

2019-09-27  本文已影响0人  居居居居居居x

前言

在网上看到许多的关于Android消息机制的讲解,觉的还是自己重新看书并自己写一篇来理解会更好,消息机制的内容也是在面试中最容易被问到的内容,因为消息机制的内容比较多,我会分成好几篇来进行讲解,有错误也请大家多多包涵并指出。

消息机制是什么

从一般角度来说,Android的开发机制指的就是Handler,它是Android消息机制的上层接口,我们只需要对他进行交互就好了,它也是Android开发中最经常接触的一个消息机制,Handler默认关联主线程,虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。对于一些异步的耗时操作还有最重要的更新UI这些就都需要通过Handler来进行实现,我们也就从这里开始入手。

Handler的基本使用

package com.ju.handlerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class HandlerActivity extends AppCompatActivity {


    private Button b1;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 1:
                    //这里更新业务逻辑或者更新UI
                    break;
                default:
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        b1 = findViewById(R.id.button1);
        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        //这个是标志,可以发送多个,比如arg1,arg2等等。
                        message.what = 1;
                        handler.sendMessage(message);
                    }
                }.start();
            }
        });
    }
}

这里先创建了一个Handler的对象,并重写了handleMessage()的方法,这个方法就是执行主要的业务逻辑的,然后创建了一个子线程,在子线程里面创建了一个Message的对象,这个Message就是Handler要处理的对象,Message有多个字段。

public void testMessage(){
    Message message = new Message();
    //传入的是int类型
    message.what = 1;
    message.arg1 = 2;
    message.arg2 = 3;
    //传入的是Object类型
    message.obj = null;
}

我们发现不仅是可以传入int值,其实也可以传入Object的类型,这样Handler就可以执行一些更复杂的操作了,然后在通过sendMessage()这个方法来把消息发送出去,message对象就会传到Handler的handleMessage()里根据字段进行具体的业务逻辑处理。注意的是Handler的handleMessage()这时候就已经是在主线程中进行了,而不是在子线程中进行运行。这就是最基本的使用方法了。

Handler工作原理

这里我们就先不从源码开始解析(因为源码有点多= =),这里大概的讲解一下Handler的工作原理,Handler主要就是由4个部分组成:Message、Handler、MessageQueue和Looper。而Handler的运行的底层就需要有
MessageQueue和Looper来进行支撑。我们一个个来看它们的作用。

以上总结经过Looper发送到handleMessage()的时候,也就代表了从子线程转到了主线程,这样就可以进行UI的处理了,这里补充一句,关于UI更新还有一个方法就是runOnUiThread()方法,它也是一个异步消息的接口封装,背后的原理其实跟上面描述的原理是一样的。

Message

发现没有,如果要进行Handler的传递,就一定需要一个Message,但是如果每次需要调用的Handler的时候就创建一个Message实例化的话,又会非常的浪费资源。其实创建Message有其它的方法。

//通过Handler取出Message
Message message1 = handler.obtainMessage();
//通过Message自带的obtain()来取出Message
Message message2 = Message.obtain();

我们这里先看第一种的源码吧

//Handler类
public final Message obtainMessage()
{
    return Message.obtain(this);
}

//Message类
public static Message obtain(Handler h) {
    Message m = obtain();
    m.target = h;

    return m;
}

//也是第二种绑定方式的源码
public static Message obtain() {
    synchronized (sPoolSync) {
        if (sPool != null) {
            Message m = sPool;
            sPool = m.next;
            m.next = null;
            m.flags = 0; // clear in-use flag
            sPoolSize--;
            return m;
        }
    }
    return new Message();
}

Handler类里的obtainMessage()其实就是调用了Message的obtain()方法,然后再去调用了Message内部类的obtain()方法来返回Message。而第二种绑定方式就是直接调用了obtain()就直接创建了Message,这样子的效率其实是会更高的,源码这里发现其实Message是一个链表,这里判断如果是空链表的话,就创建一个Message,然后将头链表移除掉,将头链表的下一个作为新的节点,并维护sPoolSize,sPoolSize就是节点数量,而且还加了个synchronized的锁。这样子就减少了对Message的重复利用,也不会一直创建Message对象,提高了效率。

obtain实现流程图,侵删



Handler的发送

Handler的发送方法有很多,这里说几个比较常见的。

Handler的内存泄露

其实如果直接调用重写Handler的handlerMessage()是有可能会引起内存泄露的,官方并不建议这样使用Handler,可以按照官方给出的解决办法的使用方法。

private Handler mHandler = new Handler(new Handler.Callback() {  
         
       @Override  
       public boolean handleMessage(Message msg) {  
           return false;  
       }  
   });



参考

上一篇下一篇

猜你喜欢

热点阅读