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

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

Handler().postDelayed({
context?.let {
//code
}
}, 3000)
138146 次浏览
遗嘱执行人
.< p>使用Executor而不是handler获取更多信息 要实现post delay,使用ScheduledExecutorService:

ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = () -> {
public void run() {
// Do something
}
};
worker.schedule(runnable, 2000, TimeUnit.MILLISECONDS);

考虑使用协程

scope.launch {
delay(3000L)
// do stuff
}

被弃用的函数是Handler的构造函数。使用Handler(Looper.myLooper()) .postDelayed(runnable, delay)代替

根据文档(https://developer.android.com/reference/android/os/Handler处理程序()):

在Handler构造过程中隐式地选择一个Looper可能会导致操作无声地丢失(如果Handler不期望新任务并退出)、崩溃(如果处理程序有时在没有Looper活动的线程上创建)或竞态条件(处理程序所关联的线程不是作者预期的线程)。相反,使用Executor或显式指定Looper,使用Looper#getMainLooper, {link android.view。查看#getHandler}或类似内容。如果为了兼容性需要隐式线程本地行为,请使用new Handler(loop . mylooper())向读者说明这一点。

我们应该停止使用没有Looper的构造函数,而是指定一个Looper。

如果你想避免Kotlin中的空检查(?!!),你可以使用Looper.getMainLooper(),如果你的Handler正在与一些UI相关的东西一起工作,就像这样:

Handler(Looper.getMainLooper()).postDelayed({
Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)

注意:如果使用fragment,请使用requireContext()而不是this@MainActivity

使用这个

Looper.myLooper()?.let {
Handler(it).postDelayed({
//Your Code
},2500)
}
handler()等代码是由Android Studio 4.0.1生成的,例如,当一个全屏活动从头创建时。我知道有人鼓励我们使用Kotlin,我也是这样做的,但是我不时地使用示例项目来实现一个想法。 奇怪的是,当AS实际生成代码时,我们却被AS责骂。这可能是一个有用的学术活动来检查错误并修复它们,但也许AS可以为我们爱好者生成新的干净的代码

只有无参数构造函数已弃用,现在最好通过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)

在Handler构造函数中提供一个循环器

Handler(Looper.getMainLooper())

使用生命周期范围会更容易。内部活动或片段。

 lifecycleScope.launch {
delay(2000)
// Do your stuff
}

或者使用处理器

        Handler(Looper.myLooper()!!)

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

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

谷歌解释了以下原因。

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

. mylooper (), callback)

解决方案1:使用遗嘱执行人

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

Java

// 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.在后台线程执行代码

Java

// 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)

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

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

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

Java

// 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:通过使用以下构造函数之一显式指定一个循环程序。

1.执行主线程中的代码

1.1. Handler with a Looper

Java

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

芬兰湾的科特林

val mainHandler = Handler(Looper.getMainLooper())

1.2 Handler with一个Looper和一个Handler。回调

Java

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. Handler with a Looper

Java

// 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. Handler with一个Looper和一个Handler。回调

Java

// 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。

Java

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

我通常用这个

代码:

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

截图:

enter image description here

如果你使用变量作为处理程序和可运行的,然后像这样使用它。

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

协程芬兰湾的科特林

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

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

Handler()Handler(Handler.Callback callback)构造函数已弃用。因为那些会导致bug &崩溃。显式使用Executor或Looper。

对于Java

Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//do your work here
}
}, 1000);

我有3解决方案:

  1. 显式指定Looper:
    Handler(Looper.getMainLooper()).postDelayed({
    // code
    }, duration)
    
  2. 指定隐式线程本地行为:
    Handler(Looper.myLooper()!!).postDelayed({
    // code
    }, duration)
    
  3. <李>使用Thread:
    Thread({
    try{
    Thread.sleep(3000)
    } catch (e : Exception) {
    throw e
    }
    // code
    }).start()
    
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
}

对于Xamarin Android,而不是

Handler handler;
handler = new Handler();

只写

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

其余的代码都很好。