Android Handle解析

200 阅读4分钟
原文链接: www.ctolib.com

Handle 在 android 中的意义

Handle 通常用来做主线程和子线程之间的通信

Handle 是Android消息机制中的重要一员

只要是有异步线程与主线程通信都得地方就一定有 Handle

Handle 背后通信原理

首先,来创建一个使用 Handle 的案例

android.os.Handler handler = new Handler(){
  @Override
  public void handleMessage(final Message msg) {
    //这里接受并处理消息
  }
};
//发送消息
handler.sendMessage(message);
handler.post(runnable);

这里发送消息可以发送 message 和 runnable ,其实 runnable 也是 message ,发送 runnable 的时候会被封装成 message 来发送。

它分为两部分,用来处理和发送消息,发送该例子都是在主线程执行的所以并没有涉及的异步线程的通信,因为发送消息和处理消息都是在主线程,什么时候会有异步通信的情况?就比如你去请求网络后要返回数据更新 view 这时候就需要用到 handle ,但现在的大部分网络框架基本上在请求到数据后主动切换回主线程了,所以我们可以直接更新 view

//发送消息
handler.sendMessage(message);
handler.post(runnable);

要创建 Handle 时,必须要先创建 Looper ,创建 Looper 的方法是调用 Looper.prepare() ,要不然直接创建 Handle 会出错

//源码可看可不看
public Handler(Callback callback, boolean async) {
//这里主要是用来做提醒handle如果不及时释放会导致内存溢出,解决方法另起一个类继承handle后者使用静态内部类。之后内部持有Activity的弱引用即可
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
//主要是这里
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

为什么我们平时使用没有创建 Looper 也不会报错,因为UI主线程已经帮我们创建过了, Looper 会与当前线程进行关联。接下来引出下一个重要的成员 MessageQueue 看意思就是一个消息队列,他的作用就是按顺序存放了一堆的待处理的 Message ,我们现在发送一个消息 handler.sendMessage(message); 发现他最终会调用 queue.enqueueMessage(msg) 这里就看的很清楚看到我们发送消息会加入到 MessageQueue 这个队列里面,接下来再来看下如何读取消息。

假设我们要在主线程处理消息

android.os.Handler handler = new Handler(){
  @Override
  public void handleMessage(final Message msg) {
    //这里接受并处理消息
  }
};

在异步线程(请求网络,创建线程。。等等操作都是在异步线程)一系列操作之后要发行消息给主线程处理 handler.sendMessage(message) (这里其实只是把消息加入到了 MessageQueue 消息队列),那主线程是怎么接收到的?

这里就要引出 Looper.loop 这个方法,前面的 Looper.prepar 方法是为了创建 Looper ,这里都得 Looper.loop 则是用来做循环,他是什么时候做循环的,来看一个完整的流程

Looper.prepar()
android.os.Handler handler = new Handler(){
  @Override
  public void handleMessage(final Message msg) {
    //这里接受并处理消息
  }
};
Looper.loop()
//发送消息
handler.sendMessage(message);
handler.post(runnable);
  1. 调用 Looper.prepar() 来创建 Looper , Looper 创建成功且与当前线程进行绑定,并且会创建一个空的 MessageQueue 消息队列
  2. 在当前线程创建 handle 来准备处理消息
  3. 调用 Looper.loop() 后,会生成一个 for(;;) 循环,这个无止境的 for 循环会不断遍历 MessageQueue 如果 MessageQueue 不为空就取出 message 发送给 Handle 处理,如果为空就继续遍历
  4. 调用 sendMessage() 将一个 message 加入到 MessageQueue 。
    至此大的流程结束,来说一下遍历 MessageQueue 时候如何将取出来的数据发送给 Handle 去处理的,因为这时发送消息是在异步线程,处理在主线程处理,当 Looper 从他的 MessageQueue 中取出这条 msg 之后,会调用 msg 的 msg.target.dispatchMessage(msg) ,而 msg.targer 就是我们主线程中的 Handle ,这样消息就回到了 handMessage 中

msg.targer是什么时候赋值为主线程的 Handle 的?就是我们在调用 handle.sendMessage(message) 这句话的时候,他不仅仅将 message 加入到 MessageQueue 还会设置该条 message 的targer设置为 this 即 Handle

handler.sendMessage(message);
handler.sendMessageDelayed(message);
handler.sendMessageAtTime(message);
handle.enqueueMessage();


private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;  
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

handle 发送消息 sendMessage 时候将一条消息加入到 MessageQuue 时候,怎么正好是 Looper 的 MessageQueue ?

在 new Handle() 的时候,内部会持有 mLooper ,有了 Looper 就可以获取到他的 MessageQueue 了

mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

查看原文: Android Handle解析