Get the FULL version

Android: how to create a loading screen – Part 2

Android: how to create a loading screen – Part 2 thumbnail

This is the second tutorial from the post series that explains how to code a loading screen on Android. The first one can be found here. This post has a similar approach to the previous one, except this time, instead of using a AsyncTask to execute code on the background thread, a Thread and Handler objects are going to be used to achieve the same results.

The Activity featured below is somewhat similar to the first post, except this time, the UI rendering related functions calls will be more scattered throughout the Activity’s body. Additionally, the Runnable interface is going to be implemented multiple times in the below code. Not only that, but now it’s necessary to “kill” the thread manually after the code executes, a task that is handled automatically by the AsyncTask class (see this thread for more info).

All code has been developed and tested in Android 2.1, and is available for download at the end of the post.

So, here’s the code:

package fortyonepost.com.lsth;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;

public class LoadingScreenActivity extends Activity implements Runnable
{
	//A ProgressDialog View
	private ProgressDialog progressDialog;
	//A thread, that will be used to execute code in parallel with the UI thread
	private Thread thread;
	//Create a Thread handler to queue code execution on a thread
	private Handler handler;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

		//Create a new progress dialog.
		progressDialog = new ProgressDialog(LoadingScreenActivity.this);
		//Set the progress dialog to display a horizontal bar .
		progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
		//Set the dialog title to 'Loading...'.
		progressDialog.setTitle("Loading...");
		//Set the dialog message to 'Loading application View, please wait...'.
		progressDialog.setMessage("Loading application View, please wait...");
		//This dialog can't be canceled by pressing the back key.
		progressDialog.setCancelable(false);
		//This dialog isn't indeterminate.
		progressDialog.setIndeterminate(false);
		//The maximum number of progress items is 100.
		progressDialog.setMax(100);
		//Set the current progress to zero.
		progressDialog.setProgress(0);
		//Display the progress dialog.
		progressDialog.show();

		//Initialize the handler
        handler = new Handler();
        //Initialize the thread
        thread = new Thread(this, "ProgressDialogThread");
        //start the thread
        thread.start();
    }

	//Initialize a counter integer to zero
	int counter = 0;

	@Override
	public void run()
	{
		try
		{
			//Obtain the thread's token
			synchronized (thread)
			{
				//While the counter is smaller than four
				while(counter <= 4)
				{
					//Wait 850 milliseconds
					thread.wait(850);
					//Increment the counter
					counter++;

					//update the changes to the UI thread
					handler.post(new Runnable()
					{
						@Override
						public void run()
						{
							//Set the current progress.
							progressDialog.setProgress(counter*25);
						}
					});
				}
			}
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}

		//This works just like the onPostExecute method from the AsyncTask class
		handler.post(new Runnable()
		{
			@Override
			public void run()
			{
				//Close the progress dialog
				progressDialog.dismiss();

				//Call the application's main View
				setContentView(R.layout.main);
			}
		});

		//Try to "kill" the thread, by interrupting its execution
		synchronized (thread)
		{
			thread.interrupt();
		}
	}
}

To use the Thread and Handler objects the first thing to do is to implement the Runnable interface. By doing this, the run() method must be overridden and defined on the Activity, which we is going to be explained in detail in the next paragraphs (line 8). At the beginning of the the above class, three member variables are being declared: a ProgressDialog object to display the background operation progress; a Handler object, to update the UI from a background thread and a Thread object, to execute code on the background (lines 11 through 15).

Next, the Activity’s onCreate() method is being defined. It initializes and displays the ProgressDialog object (lines 24 through 40). Not only that, but the handler and thread member variables are initialized. The Handler object is initialized with the default constructor. On the other hand, the Thread object is initialized by passing a Runnable and the name of the thread as a String (lines 43 and 45).

Since the Activity is implementing the Runnable interface and overriding the run() method, this can be passed as the first parameter to the Thread constructor (line 45). The thread is started in line 47, meaning that the code defined later on the run() method will be scheduled by the operational system to be executed in the recently started thread.

After the onCreate() method body, the integer counter is created and initialized to zero (line 51). Finally the aforementioned run() method is defined (lines 54 through 106). To simulate an expensive operation running on the background thread, the while block calls the wait() method of the background thread every 850 milliseconds, until the counter is equal or greater than 4 (lines 62 through 67).

Still inside this while block, the counter is incremented and the post() method is called from handler (line 70). This method updates the UI from another thread and it takes a Runnable instance as a parameter, which, in turn, requires that the virtual run() method to be defined (lines 72 through 77). Inside this inner run() method, the UI thread is updated by incrementing the progressDialog progress bar (line 76).

Then, after the thread execution is out of the while block, the handler.post() method is called again, and another Runnable is instantiated, requiring the definition of another run() method. However, this time, the progress dialog is being closed and the main view is being initialized by loading the data from the main.xml layout file (lines 88 through 99).

Finally, since we are done with the thread, there’s no need for it to be alive. For that reason, the interrupt() method is being called (lines 102 through 105).

As you can see, using the Thread and Handler objects makes the code a lot less readable than the Activity featured on the first part of this series. Although this is still useful when the background code execution can’t be solved by subclassing the AsyncTask class.

Comparing to the previous post AsyncTask method definitions, the code on the onPreExecute() method has been placed inside the onCreate() method before thread.start() has been called. The code at inside doInBackground() has basically been placed into the first run() method definition (the one that is required because of the Runnable implementation at the class declaration).

The code on onProgressUpdate() has been placed on the first handler.post() Runnable definition and the code in the onPostExecute() has been transplanted inside the second handler.post() Runnable instance.

That’s it! The above behaves much like the code on the first post of the series:

Loading screen with a progress bar.

This is what the application looks like right after it's launched. The current progress is displayed on the left and the current/remaining items are being displayed on the right.

Screenshot after the loading process.

After the loading process has finished, the progress dialog is closed and this View is loaded. Its background has been set to green on purpose to differentiate it from the previous View.

Downloads

On the next post: how to create a customized View for displaying the loading progress of a background code execution without an instance of the ProgressDialog.  Keep an eye on 41 Post for updates!

3 Comments to “Android: how to create a loading screen – Part 2”

  1. danup says:

    Very usefull.

  2. Rapsyle says:

    Thank you!!!This tutorial solved my problem after many days!

  3. Thank you, this is a great post. I will try it and develop…

    I have a media website for android developer

Leave a Comment

Post Comments RSS