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

361

我该如何修复这段代码中的弃用警告?或者,是否有其他选项可以实现相同的功能?

我该如何修复这段代码中的弃用警告?或者,是否有其他选项可以实现相同的功能?

Handler().postDelayed({
    context?.let {
        //code
    }
}, 3000)
20个回答

8
import android.os.Looper
import android.os.Handler

inline fun delay(delay: Long, crossinline completion: () -> Unit) {
    Handler(Looper.getMainLooper()).postDelayed({
        completion()
    }, delay)
}

示例:

delay(1000) {
    view.refreshButton.visibility = View.GONE
}

7

在 Handler 构造函数中提供一个 looper。

Handler(Looper.getMainLooper())

4

如果您正在使用变量作为Handler和Runnable,请按照以下方式使用:

private Handler handler;
private Runnable runnable;

handler = new Handler(Looper.getMainLooper());
    handler.postDelayed(runnable = () -> {
        // Do delayed stuff here
         handler.postDelayed(runnable, 1000);
    }, delay);

同时,您需要在 onDestroy() 方法中删除回调函数。

@Override
public void onDestroy() {
    super.onDestroy();
    if (handler != null) {
        handler.removeCallbacks(runnable);
    }
}

3
根据文档 (https://developer.android.com/reference/android/os/Handler#Handler()):
在 Handler 构造期间隐式选择 Looper 可能会导致操作被静默丢失(如果 Handler 不希望新任务并退出),崩溃(如果有时在没有活动 Looper 的线程上创建了处理程序),或竞争条件,其中处理程序关联的线程不是作者预期的。相反,使用 Executor 或显式指定 Looper,使用 Looper#getMainLooper、android.view.View#getHandler 或类似方法。如果需要兼容性的隐式线程本地行为,请使用 new Handler(Looper.myLooper()) 以便让读者清楚。
我们应该停止使用没有 Looper 的构造函数,而是指定一个 Looper。

3

Kotlin协程

private val SPLASH_SCREEN_TIME_OUT_CONST: Long = 3000

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_splash)
    window.setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN
    )
    GlobalScope.launch {
        delay(SPLASH_SCREEN_TIME_OUT_CONST)
        goToIntro()
    }

}

private fun goToIntro(){
    startActivity(Intent(this, IntroActivity::class.java))
    finish()
}

我认为GlobalScope和Handler之间没有区别。GlobalScope不会意识到生命周期(除了应用程序进程)。在我看来,根据GlobalScope,生命周期范围或自定义范围是更方便的方式。 - Cagdas

3

在Kotlin中使用这种结构是个好主意。

companion object Run {
   fun after(delay: Long, process: () -> Unit) {
      Handler(Looper.getMainLooper()).postDelayed({
          process()
      }, delay)
   }
}

稍后将其称为
Run.after(SPLASH_TIME_OUT) {
   val action = SplashFragmentDirections.actionSplashFragmentToLogin()
   v.findNavController().navigate(action)
}

2

Java答案

我编写了一个易于使用的方法。您可以直接在项目中使用此方法。delayTimeMillis可以是2000,这意味着此代码将在2秒后运行。

private void runJobWithDelay(int delayTimeMillis){
    new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        @Override
        public void run() {
            //todo: you can call your method what you want.
        }
    }, delayTimeMillis);
}

1

我通常使用这个

代码:

Handler(Looper.myLooper() ?: return).postDelayed({
           // Code what do you want
        }, 3000)

截图:

enter image description here


0

对于 Xamarin Android,不要使用

Handler handler;
handler = new Handler();

只需编写

Handler handler;
handler = new Handler(Looper.MyLooper());

代码的其余部分是没问题的。


0

当我们从头开始创建全屏活动时,Android Studio 4.0.1会生成handler()等代码。我知道我们被鼓励使用Kotlin,我也确实在使用,但有时我会使用示例项目来启发灵感。 奇怪的是,AS生成代码时却责备我们。虽然检查错误并修复它们可能是一项有用的学术活动,但也许AS可以为我们这些爱好者生成新的干净代码...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接