Handler(Handler.Callback) is deprecated
Asked Answered
R

3

6

Handler(android.os.Handler.Callback) is deprecated what should I use instead?

Handler handler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        switch(message.what) {
            case READ_MESSAGE:
                byte[] readBuff = (byte[]) message.obj;
                String tempMessage = new String(readBuff, 0, message.arg1);
                readMsg.setText(tempMessage);
                break;
        }
        return true;
    }
});
Rundell answered 28/11, 2020 at 8:57 Comment(2)
When something is deprecated it often helps to read the documentation as it typically tells you not only why but what the replacement is, if any: developer.android.com/reference/kotlin/android/os/…Eam
Perfect answer here https://mcmap.net/q/55938/-what-do-i-use-now-that-handler-is-deprecatedGeffner
R
16

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

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.

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

2. Execute code in a background thread

// 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 1 second.
backgroundExecutor.schedule(new Runnable() {
    @Override
    public void run() {
        // Your code logic goes here
    }
}, 1, 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.

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

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

1. Execute code in the main thread

1.1. Handler with a Looper

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

1.2 Handler with a Looper and a Handler.Callback

Handler mainHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
    @Override
    public boolean handleMessage(@NonNull Message message) {
        // Your code logic goes here.
        return true;
    }
});

2. Execute code in a background thread

2.1. Handler with a Looper

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

2.2. Handler with a Looper and a Handler.Callback

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

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.

// 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;
    }
});
Revareval answered 28/11, 2020 at 9:49 Comment(5)
What was the old behaviour of Handler(Handler.Callback) or Handler()?Moramorabito
@Moramorabito Since these two APIs are marked as deprecated, it means Android still supports them as long as they can, but it might not be available in the future (removed from SDK). If you keep using deprecated APIs then you must keep track of removed APIs when you update to the newest SDK. The old behaviors are not changed as long as the deprecated APIs are not removed.Revareval
Yes, but I wanted to know the behaviour of the deprecated API that I am using. On the website they only say it is deprecated now.Moramorabito
@Moramorabito Android does not change any behavior of the deprecated APIs that you are using, so you don't need to worry about that.Revareval
I just wanted to know how it works in the old way, because they have removed the documentation for the old behaviour. But I checked in the source code instead.Moramorabito
C
0

Use it in Java files,

Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
  @Override
  public void run() {
    //Code here
   }
}, 2000);

Use it in Kotlin files,

Handler(Looper.getMainLooper()).postDelayed({
    // Code here
}, 2000)
Colostrum answered 2/11, 2021 at 5:54 Comment(0)
K
0

In Kotlin, if you use Handler and Runnable , just add one key:

before

 private var handler: Handler = Handler()

after

private var handler: Handler = Handler(Looper.getMainLooper())
Kreager answered 29/1, 2022 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.