欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 11推荐使用Handler的构造方法

程序员文章站 2023-01-31 12:39:30
背景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 * current thread. *...

背景

Android 11(即API 30:Android R)弃用了Handler默认的无参构造方法
Android 11推荐使用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

推荐使用方式

  1. 使用Executor接口或者是明确指定Looper

use an {@link java.util.concurrent.Executor} or specify the
Looper explicitly

  1. 使用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();
  1. 使用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());

本文地址:https://blog.csdn.net/qq_38666896/article/details/108990831