现在 Handler() 已被弃用,我该使用什么?

新手上路,请多包涵

如何修复此代码中的弃用警告?或者,还有其他选择吗?

 Handler().postDelayed({
    context?.let {
        //code
    }
}, 3000)

原文由 Bolt UIX 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

仅不推荐使用无参数构造函数,现在最好通过 Looper.getMainLooper() 方法在构造函数中指定 Looper

将其用于 Java

 new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        // Your Code
    }
}, 3000);

将它用于 Kotlin

 Handler(Looper.getMainLooper()).postDelayed({
    // Your Code
}, 3000)

原文由 Nikunj Paradva 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

谷歌在下面解释了原因。

在 Handler 构造期间隐式选择 Looper 可能会导致操作无提示地丢失(如果 Handler 不期待新任务并退出)、崩溃(如果有时在没有激活 Looper 的线程上创建处理程序)或竞争条件,处理程序关联的线程不是作者预期的。相反,使用 Executor 或明确指定 Looper,使用 Looper#getMainLooper、{link android.view.View#getHandler} 或类似方法。如果兼容性需要隐式线程本地行为,请使用 new Handler(Looper.myLooper(), callback) 让读者清楚。

解决方案 1: 使用 执行器

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

科特林

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

// Execute a task in the main thread
mainExecutor.execute {
    // 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 3 seconds.
backgroundExecutor.schedule(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here
    }
}, 3, TimeUnit.SECONDS);

科特林

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

// Execute a task in the background thread.
backgroundExecutor.execute {
    // Your code logic goes here.
}

// Execute a task in the background thread after 3 seconds.
backgroundExecutor.schedule({
    // Your code logic goes here
}, 3, TimeUnit.SECONDS)

注意: 使用后记得关闭executor。

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

科特林

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

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

// Execute a task in the background thread.
backgroundExecutor.execute {
    // Your code logic goes here.

    // Update UI on the main thread
    mainExecutor.execute {
        // You code logic goes here.
    }
}

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

1. 在主线程中执行代码

1.1. 带 Looper 的处理程序

爪哇

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

科特林

val mainHandler = 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;
    }
});

科特林

val mainHandler = Handler(Looper.getMainLooper(), Handler.Callback {
    // Your code logic goes here.
    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());

科特林

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

// Create a handler to execute tasks in the background thread.
val backgroundHandler = Handler(handlerThread.looper)

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

科特林

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

// Create a handler to execute taks in the background thread.
val backgroundHandler = Handler(handlerThread.looper, Handler.Callback {
    // Your code logic goes here.
    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;
    }
});

科特林

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

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

// Create a handler to execute in the background thread
val backgroundHandler = Handler(handlerThread.looper, Handler.Callback {
    // Your code logic goes here.

    // Update UI on the main thread.
    mainHandler.post {

    }
    true
})

原文由 Son Truong 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题