Monday, June 23, 2014

Android Processes & Threads in Detail


The basics of Android system is like below

- When an application starts, it checks if any component of this application is already running. 
If Yes, Android system assigns the component to the same process and same thread of execution is used.
If No, Android system starts a new Linux process for the application with a single thread of execution. By default all components of the application run in same process and thread (called the "main" thread).   

However, an app can be configured to start different components in an application on different process and also can create own threads within a process. 

Processes
By default all application components should run in same process. Applications should not ideally change this configuration, but this can be controlled in the Application manifest file. Each component available, which are mainly , , , .  Each of these components are having the android:process attribute that can specify a process in which that component should run. Interestingly, we can also set the android:process such that components of different applications can also run in same process. However, this requires that the applications share the same Linux user ID and are signed with the same certificate. 

The element also supports and android:process attribute, to set a default value that applies to all components.  Android may shut down the process at some point when the memory is low and required by other processes that are more immediately serving the user. Application components running in the process thats killed are consquently destroyed. A process is started again when there is again work for that process to do. 

Android kill the process based on the relative importance of the app to the user. For e.g. if the activity is not visible on the screen, There are some rules Android system applies for choosing which application to be terminated. 

Process Life cycle
Android places each process into an importance hierarchy based on components running in the process and the state of the process. 
There are 5 levels of importance to processes. 

1. Foreground process
2. Visible process
3. Service Process
4. Background processes
5. Empty process 

Foreground Process
A process is declared as foreground in the below circumstances 

- It hosts an Activity that the user is currently interacting with. (the Activity's onResume has been called.) 
- It hosts a Service thats bound to the activity that the user is interacting with. 
- It hosts a service thats running in the foreground- a service's startInForeground has been called. 
- it hosts a service that's executing one of its life cycle callbacks. (onCreate(), onStart() or onDestroy())
- It hosts a BroadCastReceiver thats executing its onReceive() method 

the foreground processes are killed as last resort. - If memory is so low that they cannot all continue to run. At this point, of memory short scenario, Android system may kill the service to keep the user interface responsive, 

Visible Process
A process that doesn't have any foreground components, but still can affect what sees on the screen. A process is considered visible in below circumstances 

- It hosts and Activity that is not in the foreground, but is still visible to the user (its onPause method has been called). This may happen when a foreground activity started a dialog which will call a previous activity to get the onPause method. 
- It hosts a service that is bound to a visible activity. 

Service Process:
A process that is running a service that has been started with the startService method and does not fall into either of the two higher categories. Although these processes are not doing anything that user see directly, they are generally doing things imporatn to the user. For e.g. playing music in the background or downloading data on the network. 

Background process
These are processes those hold an activity those are no longer visible to the user. The activities onStop method has been called. Usually there are many background processes are running so, Android system will keep a LRU list to ensure the process with the activity that was most recently seen by the user is the last to be killed. IF an activity implements the lifecycle methods correctly and saves the current state, killing its process will not have a visible effect on the user experience. 

Empty process
These are processes that doesn't hold any active application components. The only reason to keep this kind of process alive is for cachine purposes.

Because a process running in a service is ranked higher than a process with background activities, an activity that initiates a long-tuning operation might do well to start a service for that operation, rather than simply create a worker thread. For e.e.g an activity thats uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service guarantees that the operation will have at least "service process" priority, regardless of what happens to that activity. This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread. 

Threads 
The thread that is created when an application launched is called Main thread. This important thread is the one in charge of dispatching events to the appropriate user interface widgets, including drawing events. The main thread is the one which application is using to interact with the Android UI toolkit i.e. components from the android.widget and android.view packages.  As such the main thread is also called UIThread. 

The event handling mechanism is something like below. When user is pressing on Button, the applications UI thread dispatches the touch event to the ui widget which in turn sets its pressed state to yes and posts and invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself. If UI thread is hang for more than 5 seconds, the user will be presented with the Application Not responding dialog. 

Having said this, it is also to note that the Android UI toolkit is not thread safe. So, one must not manipulate the UI from a worker thread - You must do all manipulation to the user interface from the UI thread. The simple two rules thus are: 

1. Do not block the UI thread
2. Do not access the Android toolkit outside the ui thread. 

Worker Threads
If there is some operations to be done which may take longer on a UI thread, then those should be started on worker threads or otherwise called background threads. 

public void onClick(View v)
{
new Thread (new Runnable())
{
public void run ()
{
Bitmap b = loadImageFromNetwork("http://www.example.org/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}

This may seem proper, how it is not because there is a worker thread which is not a UI thread trying to access the UI and hence it becomes thread unsafe. To avoid this, Android system gives the following options

1. Activity.runOnUIThread(Runnable)
2. View.post(Runnable)
3. View.postDelayed(Runnable,long)


Using AsyncTask
AsyncTask allows one to perform asynchronous work on your user interface. It performs a blocking operation on a worker thread and then publishes the result on the UI thread. without having to handle the threads or handles ourselves. 

To make use of AsyncTask, one must subclass AsyncTask and then implement the doInBackground callback method, which runs in a pool of background threads. To update the app UI, the app should implement onPostExecute which delivers the result from background thread in doBackgrounrTask and runs in the UI Thread. The AsyncTask can be invoked by execute method on the UI thread. 

a Quick overview of AsyncTask is below 

- One can specify the type of parameters, progress values and the final value of the task, using generics 
- The method doInBackground executes automatically on a worker thread
- onPreExecute, onPostExecute, onProgressUpdate, are all invoked on the UI thread. 
- The value returned by doInBackground is sent to the onPostExecute
- One can call publishProgress at any time to invoke doInBackground to execute the onProgressUpdate method 
- One can cancel the task at anytime from any thread. 

No comments:

Post a Comment