Introduction

In Android, we often want to perform long-running tasks using the background thread with the help of a thread class.

Basically, an Android application has two types of threads:

Lets take one example. We want to download a file from a remote server and update the UI progress bar for showing the file downloading status. For that we use a background thread to download the file from a remote server, otherwise, if we initialize a long-running task in Main Thread (UI Thread), the UI will slow

We can achieve the task with the help of background thread. However, the problem is that we want to update the UI from a background thread. The background thread will not allow us to communicate directly to the main thread.

Handler

So, we want a main thread and a background thread to communicate with the help of a Handler.

A handler act as a mediator between the background thread and the main thread.

The main uses of Handler is:

  • To schedule messages and 'runnables' to be executed at some point in the future.
  • To queue an action to be performed on a different thread than your own.

Let's see the following example:

actvity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MainActivity">
  8. <Button
  9. android:id="@+id/btnStart"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:layout_marginStart="160dp"
  13. android:layout_marginLeft="160dp"
  14. android:layout_marginTop="139dp"
  15. android:layout_marginBottom="168dp"
  16. android:text="Start"
  17. app:layout_constraintBottom_toTopOf="@+id/progressBar"
  18. app:layout_constraintStart_toStartOf="parent"
  19. app:layout_constraintTop_toTopOf="parent" />
  20. <ProgressBar
  21. android:id="@+id/progressBar"
  22. style="?android:attr/progressBarStyleHorizontal"
  23. android:layout_width="0dp"
  24. android:layout_height="0dp"
  25. android:layout_marginStart="27dp"
  26. android:layout_marginLeft="27dp"
  27. android:layout_marginEnd="27dp"
  28. android:layout_marginRight="27dp"
  29. android:layout_marginBottom="344dp"
  30. app:layout_constraintBottom_toBottomOf="parent"
  31. app:layout_constraintEnd_toEndOf="parent"
  32. app:layout_constraintStart_toStartOf="parent"
  33. app:layout_constraintTop_toBottomOf="@+id/btnStart" />
  34. <TextView
  35. android:id="@+id/txtCount"
  36. android:layout_width="match_parent"
  37. android:layout_height="wrap_content"
  38. android:textAlignment="center"
  39. app:layout_constraintBottom_toBottomOf="parent"
  40. app:layout_constraintTop_toBottomOf="@+id/progressBar"
  41. tools:layout_editor_absoluteX="132dp" />
  42. </androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.java
  1. package com.e.handler;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.os.Message;
  6. import android.util.Log;
  7. import android.view.View;
  8. import android.widget.Button;
  9. import android.widget.ProgressBar;
  10. import android.widget.TextView;
  11. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  12. private static final String TAG = "MainActivity";
  13. Button btnStar;
  14. ProgressBar progressBar;
  15. TextView txtCount;
  16. int MAX_COUNT = 100;
  17. Handler mHandlerThread;
  18. private static final int START_PROGRESS = 100;
  19. private static final int UPDATE_COUNT = 101;
  20. Thread thread;
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.activity_main);
  25. btnStar = findViewById(R.id.btnStart);
  26. progressBar = findViewById(R.id.progressBar);
  27. txtCount = findViewById(R.id.txtCount);
  28. progressBar.setMax(MAX_COUNT);
  29. btnStar.setOnClickListener(this);
  30. thread = new Thread(new Runnable() {
  31. @Override
  32. public void run() {
  33. for (int count = 0; count <= 100; count++) {
  34. try {
  35. Thread.sleep(100);
  36. } catch (InterruptedException ex) {
  37. ex.printStackTrace();
  38. }
  39. Message message = new Message();
  40. message.what = UPDATE_COUNT;
  41. message.arg1 = count;
  42. mHandlerThread.sendMessage(message);
  43. }
  44. }
  45. });
  46. }
  47. @Override
  48. public void onClick(View view) {
  49. if (view.getId() == R.id.btnStart) {
  50. mHandlerThread.sendEmptyMessage(START_PROGRESS);
  51. }
  52. }
  53. @Override
  54. protected void onResume() {
  55. super.onResume();
  56. mHandlerThread = new Handler() {
  57. @Override
  58. public void handleMessage(Message msg) {
  59. super.handleMessage(msg);
  60. if (msg.what == START_PROGRESS) {
  61. thread.start();
  62. } else if (msg.what == UPDATE_COUNT) {
  63. txtCount.setText("Progress Count : " + msg.arg1);
  64. progressBar.setProgress(msg.arg1);
  65. }
  66. }
  67. };
  68. }
  69. }

From the above example, we are trying to update UI Thread from the Background thread Using Handler.

Thanks for giving your valuable time to read this document!