• 安卓消息机制


      安卓开发在处理不同线程通信的时候有一套消息处理机制,安卓的主线程(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();

    这个只不过是自己的流水账,偶尔有一些心得,错误的地方概不负责
  • 相关阅读:
    处理流之转换流
    处理流之缓冲流 buffered
    java学习笔记 字符流Reader与Writer
    java学习笔记 OutputStream与InputStream
    java学习笔记 Map接口
    java 学习笔记 Iterator 迭代器
    java学习笔记 genenic 范形
    应急响应介绍
    安全之红蓝对抗简介
    密码学基础下篇
  • 原文地址:https://www.cnblogs.com/ashitaka/p/5849559.html
Copyright © 2020-2023  润新知