Handler in Android

Handler in Android

In Android, some times we want to perform long-running tasks using the background thread with the help of a thread class.
In Android application we have two types of threads:

  • Main Thread(UI Thread)
  • Background Thread

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 do this 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
To communicate main thread and a background thread with the help of  Handler.

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

Uses of Handler

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

 

Let see Example

XML file

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                   xmlns:app="http://schemas.android.com/apk/res-auto"
                                                   xmlns:tools="http://schemas.android.com/tools"
                                                   android:layout_width="match_parent"
                                                   android:layout_height="match_parent"
                                                   tools:context=".MainActivity">

    <Button
            android:id="@+id/btnStart"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="160dp"
            android:layout_marginLeft="160dp"
            android:layout_marginTop="139dp"
            android:layout_marginBottom="168dp"
            android:background="@color/colorPrimary"
            android:textColor="#FFF"
            android:text="Start"
            android:textSize="18sp"
            app:layout_constraintBottom_toTopOf="@+id/progressBar"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="27dp"
            android:layout_marginLeft="27dp"
            android:layout_marginEnd="27dp"
            android:layout_marginRight="27dp"
            android:layout_marginBottom="344dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/btnStart" />

    <TextView
            android:id="@+id/txtCount"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/progressBar"
            tools:layout_editor_absoluteX="132dp" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

Code in Kotlin

MainActivity.kt

package com.rrtutors.handler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
import android.R.attr.start



class MainActivity : AppCompatActivity() {
    var MAX_COUNT = 100
    var mHandlerThread: Handler? = null
    private val START_PROGRESS = 100
    private val UPDATE_COUNT = 101
    var thread:Thread?=null;
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btnStart.setOnClickListener(View.OnClickListener {
            mHandlerThread?.sendEmptyMessage(START_PROGRESS);
        })
        thread= Thread(Runnable {
            for (count in 0..100) {
                try {
                    Thread.sleep(100)
                } catch (ex: InterruptedException) {
                    ex.printStackTrace()
                }

                val message = Message()
                message.what = UPDATE_COUNT
                message.arg1 = count
                mHandlerThread?.sendMessage(message)
            }
        })

        mHandlerThread = object : Handler() {
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                if (msg.what == START_PROGRESS) {
                    thread!!.start()
                } else if (msg.what == UPDATE_COUNT) {
                    txtCount.text = "Progress Count : " + msg.arg1
                    progressBar.progress = msg.arg1
                }
            }
        }
    }
}

 

Java Code

MainActivity.java

package com.rrtutors.handler;

import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    Button btnStar;
    ProgressBar progressBar;
    TextView txtCount;

    int MAX_COUNT = 100;
    Handler mHandlerThread;
    private static final int START_PROGRESS = 100;
    private static final int UPDATE_COUNT = 101;

    Thread thread;
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnStar = findViewById(R.id.btnStart);
        progressBar = findViewById(R.id.progressBar);
        txtCount = findViewById(R.id.txtCount);
        progressBar.setMax(MAX_COUNT);

        btnStar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mHandlerThread.sendEmptyMessage(START_PROGRESS);
            }
        });

        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int count = 0; count <= 100; count++) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                    Message message = new Message();
                    message.what = UPDATE_COUNT;
                    message.arg1 = count;
                    mHandlerThread.sendMessage(message);
                }
            }
        });

        mHandlerThread = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (msg.what == START_PROGRESS) {
                    thread.start();
                } else if (msg.what == UPDATE_COUNT) {
                    txtCount.setText("Progress Count : " + msg.arg1);
                    progressBar.setProgress(msg.arg1);
                }
            }
        };
    }
}