现在 Handler() 已弃用,我该用什么?
What do I use now that Handler() is deprecated?
如何解决此代码中的弃用警告?或者,还有其他选择吗?
Handler().postDelayed({
context?.let {
//code
}
}, 3000)
使用 Executor 而不是 handler 获取更多信息 Executor。
要实现 post 延迟使用 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()):
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 Executor or specify the Looper explicitly, using Looper#getMainLooper, {link android.view.View#getHandler}, or similar. If the implicit thread local behavior is required for compatibility, use new Handler(Looper.myLooper()) to make it clear to readers.
我们应该停止使用没有 Looper 的构造函数,而是指定一个 Looper。
如果你想避免 Kotlin 中的空值检查(?
或 !!
)你可以使用 Looper.getMainLooper()
如果你的 Handler
正在使用一些 UI相关的东西,像这样:
Handler(Looper.getMainLooper()).postDelayed({
Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)
注意:如果您使用片段,请使用 requireContext()
而不是 this@MainActivity
。
使用这个
Looper.myLooper()?.let {
Handler(it).postDelayed({
//Your Code
},2500)
}
handler() 等代码由 Android Studio 4.0.1 在全屏 Activity 等从头创建时生成。我知道我们被鼓励使用 Kotlin,我也这样做了,但有时我会使用示例项目来实现一个想法。
当AS真正生成代码的时候,我们却被AS责骂,这似乎很奇怪。研究错误并修复它们可能是一个有用的学术 activity 但也许 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(Looper.getMainLooper())
使用生命周期范围更容易。在 activity 或片段内。
lifecycleScope.launch {
delay(2000)
// Do your stuff
}
或使用处理程序
Handler(Looper.myLooper()!!)
Java 回答
我写了一个方法,方便使用。您可以直接在您的项目中使用此方法。 delayTimeMillis可以是2000,就是说这段代码会运行after2秒。
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 个构造函数已弃用。
Google 下面解释原因。
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 Executor or
specify the Looper explicitly, using Looper#getMainLooper, {link
android.view.View#getHandler}, or similar. If the implicit thread
local behavior is required for compatibility, use new
Handler(Looper.myLooper(), callback) to make it clear to readers.
解决方案 1: 使用 Executor
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.
}
});
Kotlin
// 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);
Kotlin
// 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.
}
});
}
});
Kotlin
// 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 的处理程序
Java
Handler mainHandler = new Handler(Looper.getMainLooper());
Kotlin
val mainHandler = Handler(Looper.getMainLooper())
1.2 带有 Looper 和 Handler.Callback
的处理程序
Java
Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
// Your code logic goes here.
return true;
}
});
Kotlin
val mainHandler = Handler(Looper.getMainLooper(), Handler.Callback {
// Your code logic goes here.
true
})
2. 在后台线程中执行代码
2.1. 带 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());
Kotlin
// 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
的处理程序
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;
}
});
Kotlin
// 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;
}
});
Kotlin
// 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)
截图:
如果你为 Handler 和 Runnable 使用 Variable,那么就这样使用它。
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);
}
}
协程 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()
}
在 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)
构造函数已弃用。因为这些会导致错误和崩溃。显式使用 Executor 或 Looper。
对于Java
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//do your work here
}
}, 1000);
我有 3 个解决方案:
- 明确指定 Looper:
Handler(Looper.getMainLooper()).postDelayed({
// code
}, duration)
- 指定隐式线程本地行为:
Handler(Looper.myLooper()!!).postDelayed({
// code
}, duration)
- 使用
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
}
如何解决此代码中的弃用警告?或者,还有其他选择吗?
Handler().postDelayed({
context?.let {
//code
}
}, 3000)
使用 Executor 而不是 handler 获取更多信息 Executor。
要实现 post 延迟使用 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()):
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 Executor or specify the Looper explicitly, using Looper#getMainLooper, {link android.view.View#getHandler}, or similar. If the implicit thread local behavior is required for compatibility, use new Handler(Looper.myLooper()) to make it clear to readers.
我们应该停止使用没有 Looper 的构造函数,而是指定一个 Looper。
如果你想避免 Kotlin 中的空值检查(?
或 !!
)你可以使用 Looper.getMainLooper()
如果你的 Handler
正在使用一些 UI相关的东西,像这样:
Handler(Looper.getMainLooper()).postDelayed({
Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)
注意:如果您使用片段,请使用 requireContext()
而不是 this@MainActivity
。
使用这个
Looper.myLooper()?.let {
Handler(it).postDelayed({
//Your Code
},2500)
}
handler() 等代码由 Android Studio 4.0.1 在全屏 Activity 等从头创建时生成。我知道我们被鼓励使用 Kotlin,我也这样做了,但有时我会使用示例项目来实现一个想法。 当AS真正生成代码的时候,我们却被AS责骂,这似乎很奇怪。研究错误并修复它们可能是一个有用的学术 activity 但也许 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(Looper.getMainLooper())
使用生命周期范围更容易。在 activity 或片段内。
lifecycleScope.launch {
delay(2000)
// Do your stuff
}
或使用处理程序
Handler(Looper.myLooper()!!)
Java 回答
我写了一个方法,方便使用。您可以直接在您的项目中使用此方法。 delayTimeMillis可以是2000,就是说这段代码会运行after2秒。
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 个构造函数已弃用。
Google 下面解释原因。
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 Executor or specify the Looper explicitly, using Looper#getMainLooper, {link android.view.View#getHandler}, or similar. If the implicit thread local behavior is required for compatibility, use new Handler(Looper.myLooper(), callback) to make it clear to readers.
解决方案 1: 使用 Executor
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.
}
});
Kotlin
// 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);
Kotlin
// 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.
}
});
}
});
Kotlin
// 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 的处理程序
Java
Handler mainHandler = new Handler(Looper.getMainLooper());
Kotlin
val mainHandler = Handler(Looper.getMainLooper())
1.2 带有 Looper 和 Handler.Callback
的处理程序Java
Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message message) {
// Your code logic goes here.
return true;
}
});
Kotlin
val mainHandler = Handler(Looper.getMainLooper(), Handler.Callback {
// Your code logic goes here.
true
})
2. 在后台线程中执行代码
2.1. 带 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());
Kotlin
// 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
的处理程序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;
}
});
Kotlin
// 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;
}
});
Kotlin
// 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)
截图:
如果你为 Handler 和 Runnable 使用 Variable,那么就这样使用它。
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);
}
}
协程 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()
}
在 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)
构造函数已弃用。因为这些会导致错误和崩溃。显式使用 Executor 或 Looper。
对于Java
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
//do your work here
}
}, 1000);
我有 3 个解决方案:
- 明确指定 Looper:
Handler(Looper.getMainLooper()).postDelayed({ // code }, duration)
- 指定隐式线程本地行为:
Handler(Looper.myLooper()!!).postDelayed({ // code }, duration)
- 使用
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
}