创建Handler的几种方法

QuibblerQuibbler 2021-01-09 约 14 分钟 1844 次阅读

创建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):获取当前线程的Looper,Handler的工作线程在创建线程,不一定是主线程。

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;
    }

相关资料:

         Reference > Handler">Android Developers > Reference > Handler

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w