Android 11推荐使用Handler的构造方法
背景Android 11(即API 30:Android R)弃用了Handler默认的无参构造方法参考链接:Android 开发者文档指南-Handler源代码(android.os.Handler)//API 30,Android 11/*** Default constructor associates this handler with the {@link Looper} for the
背景
Android 11(即API 30:Android R)弃用了Handler默认的无参构造方法
源代码(android.os.Handler)
//API 30,Android 11
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*
* @deprecated Implicitly choosing a Looper during Handler construction can lead to bugs
* where operations are silently lost (if the Handler is not expecting new tasks and quits),
* crashes (if a handler is sometimes created on a thread without a Looper active), or race
* conditions, where the thread a handler is associated with is not what the author
* anticipated. Instead, use an {@link java.util.concurrent.Executor} or specify the Looper
* explicitly, using {@link Looper#getMainLooper}, {link android.view.View#getHandler}, or
* similar. If the implicit thread local behavior is required for compatibility, use
* {@code new Handler(Looper.myLooper())} to make it clear to readers.
*
*/
@Deprecated
public Handler() {
this(null, false);
}
- 原因:
@deprecated Implicitly choosing a Looper during Handler construction can lead to bugs
隐式的Looper会导致一些错误(场景如下)
where operations are silently lost (if the Handler is not expecting new tasks and quits),
操作丢失
crashes (if a handler is sometimes created on a thread without a Looper active), or race conditions,
程序崩溃和紊乱情况
where the thread a handler is associated with is not what the author anticipated.
非期望的Handler
推荐使用方式
- 使用Executor接口或者是明确指定Looper
use an {@link java.util.concurrent.Executor} or specify the
Looper explicitly
- 使用Looper静态方法getMainLooper()或View实例方法getHandler()
using {@link Looper#getMainLooper}, {link
android.view.View#getHandler}, or similar.
参考链接:Android开发者文档-Looper
- 方法源代码
//android.os.Looper
public final class Looper{
//...
/**
* Returns the application's main looper, which lives in the main thread of the application.
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
}
//android.view.View
@UiThread
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
//....
/**
* @return A handler associated with the thread running the View. This
* handler can be used to pump events in the UI events queue.
*/
public Handler getHandler() {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler;
}
return null;
}
}
- 例子
//Looper的静态方法getMainLooper()作为Handler构造方法的参数
private Handler looperHandler = new Handler(Looper.getMainLooper());
//view的getHandler()方法必须先存在实例对象,方法直接返回Handler对象
//@param view View的实例对象
Handler viewHandler = view.getHandler();
- 使用Looper的静态方法myLooper()
If the implicit thread local behavior is required for compatibility, use {@code new Handler(Looper.myLooper())} to make it clear to readers.
- 方法源代码:
//android.os.Looper
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
- 例子:
private Handler handler = new Handler(Looper.myLooper());
完整代码片断案例
private Handler mHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg){
Log.v(TAG, "handleMessage(" + msg + ")");
AsyncResult asyncResult;
switch (msg.what){
case Constant.EVENT_DEMO:
asyncResult = (AsyncResult) msg.obj;
if (asyncResult.exception == null) {
doOperation(asyncResult);
} else {
Log.d(TAG, "doOperation asyncResult.exception = " + asyncResult.exception);
}
break;
default:
Log.e(TAG, "Unknown msg " + msg.what);
break;
}
}
};
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)