Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What do I use now that Handler() is deprecated?

How do I fix the deprecation warning in this code? Alternatively, are there any other options for doing this?

Handler().postDelayed({
    context?.let {
        //code
    }
}, 3000)
like image 592
Hari Shankar S Avatar asked Oct 08 '22 17:10

Hari Shankar S


People also ask

What is the replacement of handler in Kotlin?

To execute the handler in the current thread, then you have to retrieve the Looper of the current thread by using the Looper. myLooper method. The constructor new Handler(Looper. myLooper(), callback) is the exact alternative to the aforementioned deprecated methods.

What is use of handler in Android?

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue . Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler it is bound to a Looper .

How do you use kotlin handler?

You can use Handler to add a Runnable object or messages to the Looper to execute the code on the thread associated with the Looper. Android associates each Handler instance with a single thread and that thread's message queue. Whenever you create a new Handler instance, it is tied up to a single Looper .

How do you use kotlin handler postDelayed?

The postDelayed method takes two parameters Runnable and delayMillis . It adds the Runnable to the thread's message queue to be run after the specified amount of time elapses. The Runnable will execute on the thread to which this handler is attached.


3 Answers

Only the parameterless constructor is deprecated, it is now preferred that you specify the Looper in the constructor via the Looper.getMainLooper() method.

Use it for Java

new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
    @Override
    public void run() {
        // Your Code
    }
}, 3000);

Use it for Kotlin

Handler(Looper.getMainLooper()).postDelayed({
    // Your Code
}, 3000)
like image 159
Nikunj Paradva Avatar answered Oct 21 '22 00:10

Nikunj Paradva


If you want to avoid the null check thing in Kotlin (? or !!) you can use Looper.getMainLooper() if your Handler is working with some UI related thing, like this:

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

Note: use requireContext() instead of this@MainActivity if you are using fragment.

like image 39
Nicolas Jafelle Avatar answered Oct 21 '22 00:10

Nicolas Jafelle


From API level 30, there are 2 constructors are deprecated.

  • Handler()

  • Handler(Handler.Callback)

Google explains the reason below.

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.

Solution 1: Use an Executor

1. Execute code in the main thread.

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. Execute code in a background thread

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)

Note: Remember to shut down the executor after using.

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

3. Execute code in a background thread and update UI on the main thread.

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.
    }
}

Solution 2: Specify a Looper explicitly by using one of the following constructors.

  • Handler(Looper)

  • Handler(Looper, Handler.Callback)

1. Execute code in the main thread

1.1. Handler with a Looper

Java

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

Kotlin

val mainHandler = Handler(Looper.getMainLooper())

1.2 Handler with a Looper and a 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. Execute code in a background thread

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

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

Note: Remember to release the thread after using.

handlerThread.quit(); // or handlerThread.quitSafely();

3. Execute code in a background thread and update UI on the main thread.

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
})
like image 73
Son Truong Avatar answered Oct 21 '22 00:10

Son Truong