Android multithreading is very useful if you want to create an Android app with very good user experience, but how do you know which technique gonna solve your problem? The default Android SDK provides some tools for asynchronous programming. And the default JVM has its own multithreading environment. We gonna learn and start exploring some of them to make our app don’t wait for a long-running task like network calls, do some heavy calculations or even trying to access the database that is already heavy with lots of data.
Thread Basics
Programming is all about instructing the hardware to perform an action (e.g., show images on a monitor, store data on the filesystem, etc.). The instructions are defined by the application code that the CPU processes in an ordered sequence, which is the high-level definition of a thread. From an application perspective, a thread is an exe‐the prosecution along a code path of Java statements that perform sequentially. A code path that is sequentially executed on a thread is referred to as a task, a unit of work that coherently executes on one thread. A thread can either finish one or multiple tasks in sequence.
Android Multithreading in Application development
UI Threads
Android threads are based on the native threads in Linux with a Thread representation in Java, but the platform still assigns special properties to threads that make them differ. The Android threads types are UI, binder and background threads. The UI thread starts on the application start and stays alive during the lifetime of the Linux process. The UI thread is the main thread of the android application which is used for executing Android components and updating the UI elements on the screen.
If the platform detects that UI updates are attempted from any other thread, it will fast notify the application by throwing a CalledFromWrongThreadException. This harsh platform behavior is required because the Android UI Toolkit is not thread-safe, so the runtime allows access to the UI elements from one thread only
Binder Threads
Threads in different processes use for communicating Binder threads. Each process consists of a set of threads called a thread pool, which is never terminated or recreated but can run tasks at the request of another thread in the process. These threads handle incoming requests from other processes, including system services, intents, content providers, and services. When needed, the incoming request will create a new binder thread to handle. In most cases, an application does not have to be con‐ concerned about binder threads because the platform normally transforms the requests to use the UI thread first. The exception is when the application offers a Service that can be bound from other processes via an AIDL interface
Background Threads
All the threads that an application unusually creates are background threads. This means that they have no predefined objective, but are empty execution environments waiting to execute any task. The background threads are descendants of the UI thread, so they inherit the UI thread properties, such as its priority. By default, a newly created process doesn’t contain any
So now we know some very basics of threads in the theory of Android. We need to go through some real-life implementation of android multithreading to understand better! Hint: We are not going to discuss subjects like RxJava or reactive programming in this article, this article is for the beginner of Android to understand android multithreading better!
/** * A very simple thread demo. * basically starts a thread to display the progress from 0 to 100 (in increments of 5). */ public class MainActivity extends AppCompatActivity { TextView Progress; int ProgressValue; Button Button1; //for threading and communication, protected Handler handler; //for the thread Thread myThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Progress = findViewById(R.id.textView1); Button1 = findViewById(R.id.button1); Button1.setOnClickListener(new Button.OnClickListener() { /* * starts the Thread. */ @Override public void onClick(View view) { myThread = new Thread(new CountingThread(0)); myThread.start(); } }); //message handler for the animation. handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == 0) { // update progress. Progress.setText("Progress: " + ProgressValue + "%"); } else if (msg.what == 1) { //finished. Progress.setText("Completed: " + ProgressValue + "%"); } return true; } }); } class CountingThread implements Runnable { int i = 0; //default value of zero. CountingThread(int start) { i = start; //starting value for the count. } @Override public void run() { while (i < 100) { SystemClock.sleep(250); i++; if (i % 5 == 0) { //update UI ProgressValue = i; //send message to update the screen. handler.sendEmptyMessage(0); } } ProgressValue = i; handler.sendEmptyMessage(1); //we are done! } } }
The above codes run and show progress to the text view with steps of 5 from 0 to 100. We did the calculation on the background thread. And also we need to know that, all UI runs in the main thread of Android. So need to update the UI on the main thread. That’s where we need to use a handler to update the UI at the main thread by sending a message from the background thread data updates!
Let me give you a brief on the above code for the very beginner for a better understanding!
We basically have a Button to start the process, a TextView to show the progress coming from the background thread and an integer type variable to keep the progress track in all the scope. A global variable declares all these.
Also, we are using two other objects that are Thread and another is Handler. A separate thread or another pool of execution on the processor uses a Thread class for starting. And we are using the Handler class for communicating with the background thread to the main thread(UI Thread) as we know that the main thread is only responsible for updating the UI.
If you read the code carefully and see the comments I did for your understanding you will explore that, this is a very easy implementation of the android multithreading.
Let’s explore some from the Android SDK!
AsyncTask
Android AsyncTask going to do background operation on background thread and update on the main thread. In android, we can’t directly touch background thread to the main thread in android development. The async task helps us to make communication between background thread to the main thread.
Functions of AsyncTask
Let’s see it in Action: private class AsyncTaskHelper extends AsyncTask<String, String, String> { @Override protected String doInBackground(String... params) { } @Override protected void onPostExecute(String result) { // execution of result of Long time consuming operation } @Override protected void onPreExecute() { } @Override protected void onProgressUpdate(String... text) { } }
The above code is a basic setup of the Android async task class.
onPreExecute() − Before starting the main execution calls this method. We can do our basic setup or variable initialization on this method
doInBackground(Params) − In this method, we have to do background operation on a background thread. Operations in this mechanism should not touch on any main thread
onProgressUpdate(Progress…) − When the background process is running, we can use this function to update the main thread.
onPostExecute(Result) − We will get the final result of the execution of here
Summary
All thread types in Android—UI, binder, and background—are Linux Posix threads. An application has a UI thread and binder threads when the process started. But the application has to create background threads itself. All Android components execute on the UI thread by default. But long-running tasks should execute on background threads to avoid slow UI rendering and the risk for ANRs. The UI thread is the most important thread. But it gets no special scheduling advantage compared to the other threads—the scheduler is unaware of which thread is the UI thread. Instead, it is up to the application to not let the background threads interfere more than necessary with the UI thread—typically by lowering the priority and letting the less important background threads execute in the background control group.
Final words
I tried to share some very basic concepts and ways of using thread for multi-processing in Android. Though for professional working we using RXJava, LiveData or another wrapper like Retrofit. It already has some implemented working upon this low-level threading. But always remember that only low-level mechanism knowledge can make you a pro! Good luck with learning!