【问题标题】:Handler(Handler.Callback) is deprecatedHandler(Handler.Callback) 已弃用
【发布时间】:2021-03-10 20:42:23
【问题描述】:

Handler(android.os.Handler.Callback) 已弃用,我应该改用什么?

Handler handler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        switch(message.what) {
            case READ_MESSAGE:
                byte[] readBuff = (byte[]) message.obj;
                String tempMessage = new String(readBuff, 0, message.arg1);
                readMsg.setText(tempMessage);
                break;
        }
        return true;
    }
});

【问题讨论】:

标签: java android android-handler


【解决方案1】:

从 API 级别 30 开始,有 2 个构造函数被弃用。

Google 解释了以下原因。

隐式选择 Looper 处理程序构造可能导致操作静默的错误 丢失(如果处理程序不期待新任务并退出),崩溃 (如果有时在没有 Looper 的线程上创建处理程序 活动)或竞争条件,其中与处理程序关联的线程 与作者的预期不同。相反,使用 Executor 或 明确指定 Looper,使用 Looper#getMainLooper, {link android.view.View#getHandler},或类似的。如果隐式线程 本地行为是兼容性所必需的,请使用新的 Handler(Looper.myLooper(), callback) 让读者一目了然。

解决方案 1: 使用 Executor

1.在主线程中执行代码。

// Create an executor that executes tasks in the main thread. 
Executor mainExecutor = ContextCompat.getMainExecutor(this);

// Execute a task in the main thread
mainExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // You code logic goes here.
    }
});

2.在后台线程中执行代码

// Create an executor that executes tasks in a background thread.
ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();

// Execute a task in the background thread.
backgroundExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here.
    }
});

// Execute a task in the background thread after 1 second.
backgroundExecutor.schedule(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here
    }
}, 1, TimeUnit.SECONDS);

注意:使用后记得关闭执行器。

backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();

3.在后台线程中执行代码并在主线程中更新UI。

// Create an executor that executes tasks in the main thread. 
Executor mainExecutor = ContextCompat.getMainExecutor(this);

// Create an executor that executes tasks in a background thread.
ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();

// Execute a task in the background thread.
backgroundExecutor.execute(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here.
        
        // Update UI on the main thread
        mainExecutor.execute(new Runnable() {
            @Override
            public void run() {
                // You code logic goes here.
            }
        });
    }
});

解决方案 2: 使用以下构造函数之一显式指定 Looper。

1.在主线程中执行代码

1.1. 带有 Looper 的处理程序

Handler mainHandler = new Handler(Looper.getMainLooper());

1.2 带有 Looper 和 Handler.Callback 的处理程序

Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        return true;
    }
});

2.在后台线程中执行代码

2.1. 带有 Looper 的处理程序

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute tasks in the background thread.
Handler backgroundHandler = new Handler(handlerThread.getLooper()); 

2.2. 带有 Looper 和 Handler.Callback 的处理程序

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute taks in the background thread.
Handler backgroundHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        return true;
    }
});

注意:使用后记得释放线程。

handlerThread.quit(); // or handlerThread.quitSafely();

3.在后台线程中执行代码并在主线程中更新UI。

// Create a handler to execute code in the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

// Create a background thread that has a Looper
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();

// Create a handler to execute in the background thread
Handler backgroundHandler = new Handler(handlerThread.getLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        
        // Update UI on the main thread.
        mainHandler.post(new Runnable() {
            @Override
            public void run() {
                
            }
        });
        
        return true;
    }
});

【讨论】:

  • Handler(Handler.Callback) 或 Handler() 的旧行为是什么?
  • @JohnyTex 由于这两个 API 被标记为已弃用,这意味着 Android 仍然尽可能支持它们,但将来可能无法使用(从 SDK 中删除)。如果您继续使用已弃用的 API,则必须在更新到最新的 SDK 时跟踪已删除的 API。只要不删除已弃用的 API,旧的行为就不会改变。
  • 是的,但我想知道我正在使用的已弃用 API 的行为。在网站上,他们只说它现在已被弃用。
  • @JohnyTex Android 不会改变您正在使用的已弃用 API 的任何行为,因此您无需担心。
  • 我只是想知道它是如何以旧方式工作的,因为他们已经删除了旧行为的文档。但我改为检查源代码。
【解决方案2】:

Java 文件中使用它,

Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Code here
   }
}, 2000);

Kotlin 文件中使用它,

Handler(Looper.getMainLooper()).postDelayed({
    // Code here
}, 2000)

【讨论】:

    【解决方案3】:

    Kotlin中,如果你使用HandlerRunnable,只需添加一个键:

    之前

     private var handler: Handler = Handler()
    

    之后

    private var handler: Handler = Handler(Looper.getMainLooper())
    

    【讨论】:

      猜你喜欢
      • 2020-07-16
      • 2014-02-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多