¿Qué uso ahora que Handler() está en desuso?
¿Cómo soluciono la advertencia de obsolescencia en este código? Alternativamente, ¿hay otras opciones para hacer esto?
Handler().postDelayed({
context?.let {
//code
}
}, 3000)
Solo el constructor sin parámetros está en desuso; ahora se prefiere especificarlo Looper
en el constructor mediante el Looper.getMainLooper()
método.
Úselo para Java
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// Your Code
}
}, 3000);
Úselo para Kotlin
Handler(Looper.getMainLooper()).postDelayed({
// Your Code
}, 3000)
Fuente: desarrollador.android.com
A partir del nivel 30 de API, hay 2 constructores que están en desuso.
Manipulador()
Controlador(Manejador.Devolución de llamada)
Google explica el motivo a continuación.
La elección implícita de un Looper durante la construcción del Handler puede provocar errores en los que las operaciones se pierden silenciosamente (si el Handler no espera nuevas tareas y se cierra), fallas (si a veces se crea un handler en un hilo sin un Looper activo) o condiciones de carrera. donde el hilo al que está asociado un controlador no es el que anticipó el autor. En su lugar, use un Ejecutor o especifique el Looper explícitamente, usando Looper#getMainLooper, {link android.view.View#getHandler} o similar. Si el comportamiento local del hilo implícito es necesario para la compatibilidad, utilice el nuevo Handler(Looper.myLooper(), callback) para dejarlo claro a los lectores.
Solución 1: utilice un ejecutor
1. Ejecute el código en el hilo principal.
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. Ejecutar código en un hilo en segundo plano.
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)
Nota: Recuerde apagar el ejecutor después de usarlo.
backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();
3. Ejecute el código en un hilo en segundo plano y actualice la interfaz de usuario en el hilo principal.
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.
}
}
Solución 2: especifique un Looper explícitamente utilizando uno de los siguientes constructores.
Controlador (Looper)
Controlador(Looper, Controlador.Devolución de llamada)
1. Ejecutar código en el hilo principal.
1.1. Controlador con un Looper
Java
Handler mainHandler = new Handler(Looper.getMainLooper());
Kotlin
val mainHandler = Handler(Looper.getMainLooper())
1.2 Controlador con Looper y 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. Ejecutar código en un hilo en segundo plano.
2.1. Controlador con un 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. Controlador con un Looper y un 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
})
Nota: Recuerde soltar el hilo después de usarlo.
handlerThread.quit(); // or handlerThread.quitSafely();
3. Ejecute el código en un hilo en segundo plano y actualice la interfaz de usuario en el hilo principal.
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
})
Si desea evitar la verificación nula en Kotlin ( ?
o !!
), puede usarla Looper.getMainLooper()
si Handler
está trabajando con algún elemento relacionado con la interfaz de usuario, como este:
Handler(Looper.getMainLooper()).postDelayed({
Toast.makeText(this@MainActivity, "LOOPER", Toast.LENGTH_SHORT).show()
}, 3000)
Nota: úselo requireContext()
en lugar de this@MainActivity
si está usando fragmento.