美文网首页
Handler系列--Handler源码简析

Handler系列--Handler源码简析

作者: 小斌_bingor | 来源:发表于2019-03-25 17:37 被阅读0次

前言

本系列文章,将分享与Handler相关的知识,包括Handler的结构,运作流程,各个类的作用、之间的关系


内容提要

本篇文章将简析Handler的作用,运作流程,以及主要方法


Handler简介

Handler是Android SDK来处理异步消息的核心类。
子线程与主线程通过Handler来进行通信。子线程可以通过Handler来通知主线程进行UI更新。
引用自--《Handler的作用与用法》

为什么需要子线程通知主线程更新UI呢?
众所周知,主线程不能进行耗时操作,子线程不能更新UI。那么普遍存在这么一种场景:主线程开启子线程,进行耗时操作(获取网络数据、做大量数据的存取、压缩图片等等),完成以后,将结果给回主线程,进行UI的更新。Handler的作用即体现于此,用作多个线程之间的桥梁


Handler用法

请自行百度、Google


Handler运作流程

Handler运作流程.png

可以看到,整个过程中

  • 1.Handler充当了收发器的角色,负责发送Msg,接收到期的Msg并在UI线程做响应
  • 2.Message作为信息媒介,传递数据
  • 3.Looper作为桥梁和调度者,负责切换线程,并让Msg回调Handler(至于怎么做的线程切换,下面解答)

重要属性

    final Looper mLooper;
    final MessageQueue mQueue;
    //自定义的消息回调
    final Callback mCallback;
    //标记是否为同步的Handler,Handler默认都会被创建为同步的
    final boolean mAsynchronous;

重要方法

public Handler(Callback callback, boolean async)

构造方法之一

  • 1.FIND_POTENTIAL_LEAKS内的逻辑,就是判断这个Handler的继承类是不是非静态的 匿名/内部/本地 类,从而提示你,你要新建的这个Handler,将有内存泄漏的风险(但是源码里面FIND_POTENTIAL_LEAKS是一个默认为false的final值,所以其实不会帮我们检测,我们需要自己去避免内存泄漏)
  • 2.获取当前线程的Looper,及其持有的Queue
  • 3.实际上,这是一个@hide的方法,我们并不能直接通过这个方法创建Handler,Handler支持以下几个方法新建,你可以看到,都是设为同步的,也就是理论上说,我们没法用这些构造方法自己创建一个异步的Handler(实际上是异步的Message),当然我们可以用反射来尝试新建异步的Handler,但是不建议这样做
    public Handler(Callback callback, boolean async) {
        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;
    }


public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback)

创建一个异步的Handler,本质上也是调用的构造方法。这里算是提供了一个构建异步Handler的方法,但是是API>=28以上才能使用的,我手上没有9.0的手机,没法尝试


private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
  • 1.这个是sendMessage系列方法最终调用的方法
  • 2.通过这里入列的消息,一定有target,这个信息在我们分析MessageQueue的时候会有用
  • 3.这里会根据mAsynchronous来设置msg的同步异步,而根据前面的分析,API<28的时候,我们理论上无法创建一个异步的Handler,那么也就是说msg必然是同步的,这个信息在我们分析MessageQueue的时候也会有用
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }


public void dispatchMessage(Message msg)
  • 1.这个方法就是最终消息到期,从消息队列出列之后,handler回调消息的地方
  • 2.如果自定义了Message的Callback,将不会走handleMessage()的逻辑
  • 3.如果自定义了Handler的Callback,也可以不在handleMessage()方法里处理回调
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

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

其他方法

obtainMessage系列方法

实际上是调用的Message的obtain系列方法,留在Message篇介绍吧

removeMessages系列方法

--public final void removeCallbacks(Runnable r)
--public final void removeCallbacks(Runnable r, Object token)
--public final void removeMessages(int what)
--public final void removeMessages(int what, Object object)
--public final void removeCallbacksAndMessages(Object token)
根据message的what/obj/handler/callback等移除message

hasMessages系列方法

--public final boolean hasMessages(int what)
--public final boolean hasMessagesOrCallbacks()
--public final boolean hasMessages(int what, Object object)
--public final boolean hasCallbacks(Runnable r)
通过what/obj/handler/callback等判断消息队列中是否有对应的message

public final void dump(Printer pw, String prefix)

打印当前的消息队列信息


相关类介绍

  • Looper

Handler系列--Looper简析

  • MessageQueue

Handler系列--MessageQueue

  • Message

Handler系列--Message简析

本篇内容到此结束,感谢收看~~

相关文章

网友评论

      本文标题:Handler系列--Handler源码简析

      本文链接:https://www.haomeiwen.com/subject/bwvspqtx.html