创建Handler的几种方法

Quibbler 2021-1-9 1352

创建Handler的几种方法


        Android开发中常常用到Handler,通常开发者通过构造函数直接 new 一个Handler使用。还有哪几种方法可以获取到实例?



1、构造方法

        通过Handler类的构造方法,我们可以获取到Handler实例。构造方法中有一个Callback回调接口,它的作用详见Handler中Callback的作用


1.1、废弃方法

        在API 30的源码中下面这两个方法已经被框架标记为@deprecated,不建议再使用。它们也是内部再调用1.2节中的第三个构造方法。

        Handler()

    @Deprecated
    public Handler() {
        this(null, false);
    }

        Handler(Callback callback)

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

        之所以废弃,是因为最终都调用下面这个分发,没有指定Looper,使用的是当前线程的Looper,不够明确:

    public Handler(@Nullable 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;
        mIsShared = false;
    }


1.2、可用构造方法

        建议用以下这三种构造方法创建Handler实例:

        Handler(Looper looper)内部是调用1.3节中的第一个含有三个构造参数的方法

    /**
     * Use the provided {@link Looper} instead of the default one.
     *
     * @param looper The looper, must not be null.
     */
    public Handler(@NonNull Looper looper) {
        this(looper, null, false);
    }

        Handler(Looper looper, Callback callback)内部是调用1.3节中的第一个含有三个构造参数的方法

    /**
     * Use the provided {@link Looper} instead of the default one and take a callback
     * interface in which to handle messages.
     *
     * @param looper The looper, must not be null.
     * @param callback The callback interface in which to handle messages, or null.
     */
    public Handler(@NonNull Looper looper, @Nullable Callback callback) {
        this(looper, callback, false);
    }


1.3、应用侧不支持的构造方法

        一下这两个方法虽然是public,但是被@UnsupportedAppUsage/@hide标记为不支持应用调用的方法。

        Handler(boolean async)调用1.2节中的第三个方法,不建议开发者使用

    @UnsupportedAppUsage
    public Handler(boolean async) {
        this(null, async);
    }

        Handler(Callback callback, boolean async):获取当前线程的LooperHandler的工作线程在创建线程,不一定是主线程。

    public Handler(@Nullable 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;
    }

        Handler(Looper looper,Callback callback, boolean async):最终的构造方法

    @UnsupportedAppUsage
    public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

        应用开发者无法使用上面这几个构造方法:



2、通过静态方法创建

        Handler还有几个静态方法,可以用来获取Handler实例。


2.1、创建同步Handler

        从API 28开始,Google新增了两个API,因为之前创建Handler方法大都默认Message为非同步的。这里提一下消息的同步状态:如果mAsynchronous为true,处理程序对发送到它的Message或发送到它的Runnable任务调用Message中的setAsynchronous(boolean)方法。而这关系到消息是否异步,如果是异步的这意味着Message不受Looper同步障碍的限制。

         createAsync(Looper looper)要求API 至少是28

    @NonNull
    public static Handler createAsync(@NonNull Looper looper) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        return new Handler(looper, null, true);
    }

        createAsync(Looper looper,Callback callback)要求API 至少是28

    @NonNull
    public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
        if (looper == null) throw new NullPointerException("looper must not be null");
        if (callback == null) throw new NullPointerException("callback must not be null");
        return new Handler(looper, callback, true);
    }


2.2、框架内部两个静态

        这两个方法开发者可以参考一下,比较有用的。虽然应用层无法调用这个方法,但是对开发应用层或许有一些启发吧。

        getMain():看到这个方法的时候有点小惊喜,可以全局获取唯一的Handler。但是仔细一看,@UnsupportedAppUsage而且是hide,应用层无法使用,而且也不是线程安全的单例模式,所以开发者要想获取全局唯一的Main Handler,就自己实现一个吧。

    /** @hide */
    @UnsupportedAppUsage
    @NonNull
    public static Handler getMain() {
        if (MAIN_THREAD_HANDLER == null) {
            MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
        }
        return MAIN_THREAD_HANDLER;
    }

        mainIfNull(Handler handler):hide方法,内部使用。

    /** @hide */
    @NonNull
    public static Handler mainIfNull(@Nullable Handler handler) {
        return handler == null ? getMain() : handler;
    }



相关资料:

        Android Developers > Reference > Handler


不忘初心的阿甘
最新回复 (0)
    • 安卓笔记本
      2
        登录 注册 QQ
返回
仅供学习交流,切勿用于商业用途。如有错误欢迎指出:fluent0418@gmail.com