¿Qué uso ahora que Handler() está en desuso?

Resuelto Bolt UIX asked hace 54 años • 20 respuestas

¿Cómo soluciono la advertencia de obsolescencia en este código? Alternativamente, ¿hay otras opciones para hacer esto?

Handler().postDelayed({
    context?.let {
        //code
    }
}, 3000)
Bolt UIX avatar Jan 01 '70 08:01 Bolt UIX
Aceptado

Solo el constructor sin parámetros está en desuso; ahora se prefiere especificarlo Looperen 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

Nikunj Paradva avatar Sep 11 '2020 17:09 Nikunj Paradva

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
})
Son Truong avatar Dec 01 '2020 00:12 Son Truong

Si desea evitar la verificación nula en Kotlin ( ?o !!), puede usarla Looper.getMainLooper()si Handlerestá 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@MainActivitysi está usando fragmento.

Nicolas Jafelle avatar Jun 19 '2020 19:06 Nicolas Jafelle