Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handler(Handler.Callback) is deprecated

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;
    }
});
like image 588
Anirudh Mitra Avatar asked Nov 28 '20 08:11

Anirudh Mitra


People also ask

Is handler deprecated in android?

Handler() and Handler(Handler. Callback callback) constructors are deprecated. Because those can leads to bugs & crashes. Use Executor or Looper explicitly.

What is the use of handler in android?

In android Handler is mainly used to update the main thread from background thread or other than main thread. There are two methods are in handler. Post() − it going to post message from background thread to main thread using looper.

What are handlers and loopers in android?

Looper is an abstraction over event loop (infinite loop which drains queue with events) and Handler is an abstraction to put/remove events into/from queue with events (which is drained by Looper) and handle these events when they are processed.


1 Answers

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.

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

  • Handler(Looper)

  • Handler(Looper, Handler.Callback)

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;
    }
});
like image 199
Son Truong Avatar answered Oct 15 '22 13:10

Son Truong