Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

How to work with threads and timers in Android Applications

The article focuses on the process to work with the threads and timers in androids applications that have proved to be the necessity of multi-threaded environment these days.

Most software applications nowadays run in multi-threaded environment to take advantage of the CPU time to the highest level. Running on multiple threads enables to utilize the CPU time when one context is idle to do something else in another context.

There are differences between: thread, task and process. A thread is a piece of program that runs in parallel (almost considering round-robin revolving in single core processors, or literally parallel in multi-core processors) with other threads. Two pieces of codes on two different threads are executing in the same time. However, there is couple of methods to make synchronization between them if needed in an application. On the other hand, a task is a piece of code that runs in sequence with other tasks. However, tasks can interrupt each others. In general, differentiation between tasks and threads is marginal and the two terms may be used interchangeably. A process is a program that can run on single thread or can be divided between multiple threads. In other words, a piece of a process can run in certain thread with certain ID and another piece of the same process might run on another thread with separate ID.

Any operating system provides the multiple threading capabilities. Android OS provides this capability as well through few classes: Thread (java class), AsyncTask, Timer, etc.

It is good practice to perform long running operations or operations that block execution until they complete (e.g., file and database access) outside the GUI thread. This helps maintain application responsiveness and avoid Activity Not Responding (ANR) dialogs that appear when Android thinks the GUI is not responsive.

For example, when we need a database operation’s results in the GUI thread, we’ll use an AsyncTask (package android.os) to perform the operation in one thread and receive the results in the GUI thread. The details of creating and manipulating threads are handled for you by class AsyncTask, as are communicating the results from the AsyncTask to the GUI thread.

A thread has the following states between which a state machine is run:

  • Blocked : The thread is blocked and waiting for a lock
  • New : The thread has been created, but has never been started.
  • Runnable : The thread may be run.
  • Terminated : The thread has been terminated.
  • Timed waiting : The thread is waiting for a specified amount of time.
  • Waiting : The thread is waiting.

Normally a thread starts by invoking the start() API. Now it is ready to run and it is runnable. If the thread stops due to some delay, like resources access or memory access then it gets blocked. When the thread finishes it is then terminated. We can make the thread waits or suspend for a while or indefinitely, hence it is timed waiting or just waiting.

Messages can be exchanged between threads. Messages are send by sendMessage method on the concerned thread. First the message object is formulated, with whatever arguments and then sent. The message is handled in the receiver thread in a Handler() class inside the handleMessage () overridden method of the Handler () class. The message is put in a queue until its turn comes to be handled. Messages passing is asynchronous in this way.

Timer delays are needed in many applications, for example when a home screen needs to be launched after welcome screen, a small period is needed in between to let the welcome screen static for a while. This is achieved by using the timer class.

Running and suspending a thread

A thread has a particular class in Java called “Thread” which your thread should implement. This step is mandatory because you need to customize two methods:

Run ( ) ( or equivalently start ( ) ) : you need to implement ( override ) this method to put your code that will execute in this thread. This is the main entry point of the thread when it starts.

Message handler ( instance of Handler ( ) ) and override handleMessage ( ) method. The code you write here will execute as long as the thread messages queue is not empty. Each message will be processed in turn inside this method. It is the responsibly of the implemented code to check on which message to be handled. Arg1 can be used to identify messages ID’s. Also, the “what” parameter of the message object can be used.

The following example shows a thread called “MyThread” which implements the “ run ( ) ” method and the “ handleMessage ( ) ”. The run only listens for a button to be clicked to send message to the main thread that called this one (an instance is saved when the thread is started). Also it keeps toggling an on/off button reflecting the thread status, which toggles every “DELAY” seconds thanks to the post delayed method.

Listing 1: Post delayed enables executing a runnable each “DELAY” seconds and this happens on the same calling thread context.

package mine.testprojects.com;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class Mythread extends Thread 
{
	private TextView threadText;
	private final int DELAY = 5000;
	private boolean start;
	private boolean running;
	private Handler mainThreadHandler;
	private Button sendMsgToMain;
	
	public Mythread(TextView textBox, Handler mainThreadHandler, Button sendMsgToMain, TestThreadActivity parent)
	{
		this.threadText = textBox;
		this.mainThreadHandler = mainThreadHandler;		
		this.sendMsgToMain = sendMsgToMain;
		// doesn't work to pass the uninitialized instance to be initialized here, no pass by reference in Java
        Handler childThreadHandler = new Handler()
        {
        	@Override
        	public void handleMessage(Message msg) 
        	{
        		// TODO Auto-generated method stub
        		super.handleMessage(msg);
				Toast msg2 = Toast.makeText((Context)msg.obj, "Main Thread sent message with arg1 " + msg.arg1, Toast.LENGTH_SHORT);
				msg2.show();
        	}
        };
        
        parent.childThreadHandler = childThreadHandler;
	}
	
	@Override
	public void run() 
	{
		// TODO Auto-generated method stub
		super.run();
		running = true;
		restart();	
		
		this.sendMsgToMain.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) 
			{
				// TODO Auto-generated method stub
				Message msg = new Message();
				msg.arg1 = 10;
				msg.obj = v.getContext();
				mainThreadHandler.sendMessage(msg);
			
			}
		});
		
		
	}
	
	
    private void restart()
    {
    	Handler handler = new Handler();
    	
        handler.postDelayed(new Runnable()
        {			

			@Override
			public void run() 
			{
				// TODO Auto-generated method stub
				if(start)
				{
					if(running)
					{
						threadText.setText("Running");
						running = false;
						
					}
					else
					{
						threadText.setText("Suspended");
						running = true;
					}
				}
				restart();
			}
		}, DELAY);
    }
    
    public void setStatus(boolean start)
    {
    	this.start = start;
    }
    
    
    
}

Sending and posting messages between threads

To send a message from a thread to another, u must formulate the Message object first. The message object contains custom fields that are dependent on each case. For example you can use the arg1 parameter to pass some values.

Listing 2: Also you can use the “what” parameter as an ID to handle each message in the message handler when received by the handling thread.

sendMsgToChild.setOnClickListener(new View.OnClickListener() {
    			
    			@Override
    			public void onClick(View v) 
    			{
    				// TODO Auto-generated method stub
    				Message msg = new Message();
    				msg.arg1 = 20;
    				msg.obj = v.getContext();
    				childThreadHandler.sendMessage(msg);
    			
    			}
    		});

The message sending happens by invoking sendMessage on the thread to receive this message.

Listing 3: Handling is done in that thread inside “handleMessage”of the handler instance.

    // Inner Child Thread Class
    public class ChildThread extends Thread
    {
    	@Override
    	public synchronized void start()
    	{
			Toast msg = Toast.makeText(TestThread2Activity.this, "Child Thread Started", Toast.LENGTH_SHORT);
			msg.show();	
    	};
    	public ChildThread()
    	{
    		childThreadHandler = new Handler()
            {
            	@Override
            	public void handleMessage(Message msg) 
            	{
            		// TODO Auto-generated method stub
            		super.handleMessage(msg);
    				Toast msg2 = Toast.makeText((Context)msg.obj, "Main Thread sent message with arg1 " + msg.arg1, Toast.LENGTH_SHORT);
    				msg2.show();
            	}
            };
    	}

 Handling Thread message

Figure 1: Handling Thread message

Suspending Thread Message

Figure 2: Suspending Thread Message

Re-running thread message

Figure 3: Re-running thread message

Post delayed handling

Listing 4: Post delayed enables executing a runnable each “DELAY” seconds and this happens on the same calling thread context.

    	Handler handler = new Handler();
    	
        handler.postDelayed(new Runnable()
        {			

			@Override
			public void run() 
			{
				// TODO Auto-generated method stub
				if(start)
				{
					if(running)
					{
						threadText.setText("Running");
						running = false;
						
					}
					else
					{
						threadText.setText("Suspended");
						running = true;
					}
				}
				restart();
			}
		}, DELAY);

Asynchronous tasks

It is good practice to perform long running operations or operations that block execution until they complete (e.g., file and database access) outside the GUI thread. This helps maintain application responsiveness and avoid Activity Not Responding (ANR) dialogs that appear when Android thinks the GUI is not responsive.

You first have to override the onPreExecute, doInBackGround and onPostExecute. To execute something before starting the async task, do it in onPreExecute(). The code to run in the task itself shall be put inside doInBackGround() overridden method.

Finally onPostExecute () shall contain the code to be executed when the task ends.

Listing 5: The following example shows a computation done in background when a button is clicked.

 asyncTask.setOnClickListener(new View.OnClickListener()
        {
			
			@Override
			public void onClick(View v) 
			{
				// TODO Auto-generated method stub
				AsyncTask<Integer, Object, Integer> newAsyncTask = new AsyncTask<Integer, Object, Integer>()
				{
					
					@Override
					protected void onPreExecute() 
					{
						// TODO Auto-generated method stub
						super.onPreExecute();
	    				Toast msg2 = Toast.makeText(TestThread2Activity.this, "Async Task Started", Toast.LENGTH_SHORT);
	    				msg2.show();
					}

					@Override
					protected Integer doInBackground(Integer... params) 
					{
						// TODO Auto-generated method stub
						// Toast msgs not working here!!
	    				//Toast msg2 = Toast.makeText(TestThread2Activity.this, "Background Async Task Started, passed parameter ", Toast.LENGTH_SHORT);
	    				//msg2.show();
						int x = 10;
						
	    				
						return x*100;
					}
					
					@Override
					protected void onProgressUpdate(Object... values) 
					{
						// TODO Auto-generated method stub
						super.onProgressUpdate(values);
						// Toast msg not shown!!
	    				Toast msg2 = Toast.makeText(TestThread2Activity.this, "Executing...", Toast.LENGTH_SHORT);
	    				msg2.show();
					}
					@Override
					protected void onPostExecute(Integer result) 
					{
						// TODO Auto-generated method stub
						super.onPostExecute(result);
	    				Toast msg2 = Toast.makeText(TestThread2Activity.this, "Async Task Executed and returned" + result, Toast.LENGTH_SHORT);
	    				msg2.show();
					}
				};
				
				newAsyncTask.execute(new Integer[] {100});
				
			}
		});

Working with timers

When a home screen needs to be launched after welcome screen, a small period is needed in between to let the welcome screen static for a while. This is achieved by using the timer class as in the example below.

Listing 6: It creates a new scheduled timer task to run after DURATION which is just a constant to be defined in your code.

        new Timer().schedule(new TimerTask()
        {
			
			@Override
			public void run() 
			{
				// Start the home screen
				//finish activity doesn't work
				//WelcomeActivity.this.finishActivity(0);//Add in manifest file: android:noHistory="true" after android:name=".WelcomeActivity"
				startActivity(new Intent(WelcomeActivity.this, HomeActivity.class));
			}
		}, DURATION);

Conclusion

In this tutorial we learnt how to work with threads in Android and the different states of the thread, how to start and run a thread, how to exchange messages between threads, how to run async task in background and how to work with timers.



Have more than 5 years experience about Java, .Net, C and C++.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login