创建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;
}
相关资料:
Android Developers > Reference > Handler