Wednesday, 12 April 2023

Threading support in Android

 Hi Guys!!!

Hope you are doing well !. After long time I am back. Sorry for late to add new blogs. 

My previous post on Thread

Thread Pool in Java

Java Thread Sleep, wait, yield and join method

Today I am sharing details on threading support in Android using java.

Threading aspect is a important part of android and Its efficeint uses  in  app  improve performance significantly. 

Main thread

When an application, launched by user, Android creates a Linux process for that app and a thread of execution for it . This thread is called the main thread or UI thread of that application. 

What is main thread of an Application in Android 

The main thread is nothing but a handler thread. 

Responsibility 

    • handling events from all over the app like callbacks associated with the lifecycle information or 

    • callbacks from input events or 

    • handling events from other apps etc

Why we need another thread ?

    • The main thread does so much works (example Any block of code that needs to be run is pushed into a work queue and then serviced by the main thread).

    • it’s better to offer longer work to other threads, so as not to disturb the UI thread from its rendering duties.

    • If we do any operation that may end up keeping main thread blocked then main thread halt halt rendring job and that impact as a screen freeze .

    • If screen get freeze more than 5 sec. Android system shows ANR dialog to user 

To avoid this situation, We need a separate threads to do long operation without blocking the UI/main thread . That means these threads are executed asynchronously from the UI/main thread.

How many ways are in Android ?

Android provides many ways of creating and managing threads, and there are many third-party libraries that make thread management a lot easier. 

However, picking the right one that suits our needs is very important.

Here We explore :- 

    • Thread

    • handler

    • Looper and 

    • message queue

Thread

A java.lang.Thread object represents the most fundamental abstraction in Android’s underlying thread execution environment.

The Java virtual machine allows an application to have multiple threads of execution running concurrently.

We can create threads in two ways

1. By extending the Thread class.

class TestThread extends Thread {
@Override
public void run() {
Log.d("Threading", "Test class thread "+Thread.currentThread().getName());
}
}

2. By implementing a Runnable interface.

class TestThread implements Runnable {
@Override
public void run() {
Log.d("TestThread", "Thread using runnable "+Thread.currentThread().getName());
}
}

We need to call the start method on the thread to start the execution

new TestThread.start()


Thread Life cycle 

The thread has a lifecycle with different states like 

  • new, 
  • runnable, 
  • running, 
  • non-runnable (blocked), 
  • terminated.

We can perform any kind of operation inside threads except updating the UI elements. 
To update a UI element from a thread, we need to use either the handler or the runOnUIThread method.

Message, MessageQueue, Looper, Handler and HandlerThread 

HandlerThread 
 HandlerThread derived from the Thread class(java) and also implement the run method of it. We start it same as thread class using Thread.start() method.
 
 So What is the difference ?

  • Keep a thread alive i.e. do not let it come out of run method
  • Maintain a queue and post your task in it
  • Process the queue in your run method i.e. execute task one by one or when it comes
  • Finish/Terminate the thread once done (once you call quit method)

Looper
 Looper is a worker that keep a thread alive, It loops over message queue and send the message to respective Handler.

Handler
 This class is responsible for enqueuing any task to message queue and processing them. 
Each Handler can be associated with one single thread and that thread’s message queue.

  • creating, inserting, or removing Messages from the Message Queue
  • processing Messages on the consumer thread

Message 
The Message acts as a container for arbitrary data. The producer thread sends Messages to the Handler, which enqueues to the Message Queue. 
The Message provides three pieces of extra information, required by the Handler and Message Queue to process the message:

  • what — an identifier the Handler can use to distinguish messages and process them differently
  • time — informs the Message Queue when to process a Message
  • target — indicates which Handler should process the Message

public final Message obtainMessage()
public final Message obtainMessage(int what)
public final Message obtainMessage(int what, Object obj)
public final Message obtainMessage(int what, int arg1, int arg2)
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
 

Message Queue
This class holds the list of messages to be dispatched by the looper. You can just call Looper.myqueue() to get list of messages.
  • MessageQueue also maintains a dispatch barrier that represents the current time according to SystemClock.uptimeMillis
  • When a Message timestamp is less than this value, the message is dispatched and processed by the Handler
The Handler offers many variations for sending a Message. More Reference
public final boolean sendMessageDelayed(Message msg, long delayMillis)
public final boolean sendMessageAtFrontOfQueue(Message msg)
public boolean sendMessageAtTime(Message msg, long uptimeMillis)


How to use 
We can write our own class which extends HandlerThread. Each HandlerThread class has a looper associated with. 
We can use this looper to create Handler and then we can start enqueuing/sending message to this thread.
Steps 
  • Create a class that extend HandlerThread
  • Instantiate your handlerThread class
  • call start method (your thread is running now)
  • Create/Instantiate your Handler by using looper from handler thread created above
//Create Handler
mHandlerThread = new HandlerThread("name");
mHandlerThread.start();
Looper looper = mHandlerThread.getLooper();
mHandler = new Handler(looper);

it is a better idea to extend handler and add handling for different messages. 

if (handler == null) {
handler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SOMETHING_ACTION: {
doSomething();
break;
}
case SOMETHING_ELSE_ACTION:
doMoreThings();
break;
default:
break;
}
}
};
}
//usage
handler.obtainMessage(SOMETHING_ACTION, "");
handler.sendMessage(msg);

Note:  Call handlerThread.quit() when you are done with the background thread or on your activities onDestroy() method.

Posting back the results to the UI thread

Runnable myRunnable = new Runnable() {
@Override
public void run() {
MainActivity.this.onResult();
} // This is your code
};
mainHandler.post(myRunnable);


Thanks
Saurabh
Happy Coding!!!!

Build a Custom Kernel Module for Android

Hi Guys!!!Hope you are doing well !!!. Today I will describe how you can write a custom kernel module(Hello world) for Android and load it a...