安卓消息机制

  安卓开发在处理不同线程通信的时候有一套消息处理机制,安卓的主线程(UI线程)是不允许处理耗时任务的。所以一般耗时任务比如常见的网络下载等任务都是子线程完成,子线程完成之后通知主线程更新UI,利用Handler类实现不同线程之间的通信:

    

1:实例化Message msg = mHandler.obtainMessage();

 public final Message obtainMessage()
    {
        return Message.obtain(this);//调用的是Message类中的obtain
    }

  Handler类中obtainMessage方法实际调用的还是Message的static方法obtain(Handler);

    public static Message obtain(Handler h) { //Message中obtain的源码
        Message m = obtain();//这里是Message获取消息队列中的消息
        m.target = h;//这里会传入想要获取Message的Handler,这样就会实现Message与Handler的绑定
             //在Looper的循环中会调用Handler的dispatchMessage方法,而dispatchMessage
             //调用的还是handleMessage(..);所以在处理异步通信的时候在主线程要重写handlerMessage
             //方法来处理消息,通过what来确认消息标示
return m; }

  这里传入了Handler与消息绑定起来,这这个方法最终调用的是重载的方法obtain();

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();
    }

   这里其实先在全局的消息池中,获取Message对象,其中sPool = m.next;类似于链表里的指针域(结构类似于)next其实是Message类定义的Message对象;如果消息池中有现成的对象,就只会取出,不用重新new,如果没有就返回一个
新new的消息对象。

2:获取消息对象之后用Handler(处理器)来发送消息

  mHandler.sendMessage(msg);看看源码

  public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }

这里实际调用的是sendMessageDelayed(msg,0);这里不是延时发送消息,而是延时处理消息,只不过延时时间设定的是0;

以上获取消息发送消息都是在子线程里处理的。在主线程中用Handler类处理消息

3:Handler类的构造函数需要指定回调接口,Handler类有一个接口Callback中有一个handleMessage方法,在Handler中也有一个同名方法。

 public interface Callback {
        public boolean handleMessage(Message msg);
    }

如果不指定回调接口就要重写方法:handleMessage();

/**
     * Subclasses must implement this to receive messages.
     */
    public void handleMessage(Message msg) {
    }

注释写得很清楚如果是用Handler的子类来处理消息就必须重写这个类类接受消息。
另外也可以用匿名内部类的方式来重写接口Callback里的handleMessage;

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

获得消息之后就可以做相应的处理。首先要更具Message的what属性来确定是否是自己需要的消息,这个可以在发送消息的时候指定。
这里要明确Handler是如何处理消息的实际上是调用dispatchMessage();看源码

/**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);//这里会有限处理Message指定的回调函数
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

这个方法首先会判断Message本身是否定义了回调,如果有,那么直接调用handlerCallback(msg);

 private static void handleCallback(Message message) {
        message.callback.run();
    }

从代码可以看出最终调用的是Message调用的callback,而Message定义的callback字段实际上是Runnable接口,所以要调用run启动线程;
也就是说可以通过消息来启动一个子线程;

如果在实例化Message的时候没有指定回调就会判断mCallback是否实例化,mCallback是Handler定义的一个final CallBack接口字段。这个在

Handler实例化的时候调用对应的构造函数来指定

public Handler(Callback callback) {
        this(callback, false);
    }

如果调用的是无参构造函数的话要么用匿名内部内指定Callback,要么自己定义个Handler的子类重写handleMessage()方法。

dispatchMessage(..)也可以看出:1、如果Message实例化没有指定回调

                2、如果没有重写Handler类的接口CallBack中的 boolean handleMessage()方法

                3、最后才会执行Handler类中的方法void handlerMessage();

这个只不过是自己的流水账,偶尔有一些心得,错误的地方概不负责
原文地址:https://www.cnblogs.com/ashitaka/p/5849559.html