Android Handle解析

Handleandroid中的意义

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);
复制代码

这里发送消息可以发送messagerunnable,其实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之后,会调用msgmsg.target.dispatchMessage(msg),而msg.targer就是我们主线程中的Handle,这样消息就回到了handMessage

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

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时候,怎么正好是LooperMessageQueue? 在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;
    }
复制代码

猜你喜欢

转载自juejin.im/post/5c7f3f02e51d4541be21d4c6
今日推荐