Sunday, January 23, 2011

android.app.ProgressDialog

When your app needs to take some time to fetch data and render the UI it's considered polite to present the user with an indication that the application is working and it hasn't frozen and become unresponsive. The Android SDK has a built in ProgressDialog class defined as 'android.app.ProgressDialog'.

I added one to my ListActivity demo to show just how easy it is to work with.

In the onCreate method of my ListActivity I had code that that called a private method that hard coded the Dodad array that was shown in the ListActivity. Although I'm still going to use this method for this demo I am going to change how I'm going to call into it. I'm going to call this method using a new thread.

I'm going to implement two classes provided to us in the Java SDK. The 'Runnable' class and the 'Thread' class.

So the first step is to remove that code that looped over the Dodad array and added it to the ListActivity ArrayAdapter from the onCreate method and into it's own 'Runnable' method.

And what you get is this...

private Runnable returnRes = new Runnable()
{
@Override
public void run()
{
if(m_dodads != null && m_dodads.size() > 0)
{
for(int i=0; i < m_dodads.size(); i++) { m_adapter.add(m_dodads.get(i)); } m_adapter.notifyDataSetChanged(); } } };


Once you've done this you can remove this code from the onCreate method.

The next step is to wrap the call to getDodads() in the onCreate method of our ListActivity in Runnable class. To be specific we need to override the 'Run' method of the 'Runnable' class.

It looks like this...

runGetDodads = new Runnable()
{
@Override
public void run()
{
getDodads();
}
};

The next step is to create the Thread that will execute the 'runGetDodads' method.

It looks like this :

Thread thread = new Thread(null, runGetDodads, "getDodads");
thread.start();

At this point our main thread continues on while the thread we just created executes the getDodads() method. This is when we want to implement the ProgressDialog in our main thread.

It's really simple and the code is just like this :

m_ProgressDialog = ProgressDialog.show(Welcome.this, "One second...", "Fetching Dodads...", true);

We only need two more lines of code before we test the new ProgressDialog. We need to add the line of code that kills the ProgressDialog at the appropriate time, which would be when the getDodads() method is done fetching the Dodads. Actually we want to do it a little after that, after the ListActivity ArrayAdapter has been updated with the data set. This would be at the end of the 'Run' method of our Runnable class.

Notice the call to the 'dismiss' method of the ProgressDialog instance below.

private Runnable returnRes = new Runnable()
{
@Override
public void run()
{
if(m_dodads != null && m_dodads.size() > 0)
{
for(int i=0; i < m_dodads.size(); i++) { m_adapter.add(m_dodads.get(i)); } m_adapter.notifyDataSetChanged(); } m_ProgressDialog.dismiss(); } };


And the last line of code is meant to simulate a load time like accessing a database or a web service. Since our data is hard coded in our application it wouldn't give our ProgessDialog much chance to show itself. We'll add a strategically placed sleep statement in the getDodads() method to sleep the thread for 3 seconds.

Now we can run the app and we should see our progressDialog before the ListActivity is rendered.


Here is the complete source code for Welcome.java

package com.mydemo;

import java.util.ArrayList;

import com.mydemo.dodad.Dodad;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class Welcome extends ListActivity {

private static final String TAG = "MyDemo";

private ProgressDialog m_ProgressDialog = null;
private Runnable runGetDodads;
private ArrayList m_dodads = null;
private DodadAdapter m_adapter;

public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "Welcome onCreate() start");
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

m_dodads = new ArrayList();
this.m_adapter = new DodadAdapter(this, R.layout.dodad_row, m_dodads);
setListAdapter(this.m_adapter);

runGetDodads = new Runnable()
{
@Override
public void run() {
getDodads();
}
};

Thread thread = new Thread(null, runGetDodads, "getDodads");
thread.start();

m_ProgressDialog = ProgressDialog.show(Welcome.this, "One second...", "Fetching Dodads...", true);

Log.d(TAG, "Welcome onCreate() done");
}

private Runnable returnRes = new Runnable()
{
@Override
public void run()
{
if(m_dodads != null && m_dodads.size() > 0)
{
for(int i=0; i < m_dodads.size(); i++) { m_adapter.add(m_dodads.get(i)); } m_adapter.notifyDataSetChanged(); } m_ProgressDialog.dismiss(); } }; private void getDodads() { Log.d(TAG, "Welcome getDodads() start"); try { // Just some dummy data for the purpose of the sample // This code could easily fetch data from a server/database. m_dodads = new ArrayList();
Dodad dodad1 = new Dodad();
dodad1.setName("Dodad Number 1");
dodad1.setDescription("Cool little Dodad");
Dodad dodad2 = new Dodad();
dodad2.setName("Dodad Number 2");
dodad2.setDescription("The everyday Dodad");
Dodad dodad3 = new Dodad();
dodad3.setName("Dodad Number 3");
dodad3.setDescription("Essential do everything Dodad");
m_dodads.add(dodad1);
m_dodads.add(dodad2);
m_dodads.add(dodad3);

// This simulates the time it would take to load the Dodads
Thread.sleep(3000);

Log.d(TAG, "Welcome getDodads() returned (" + m_dodads.size() + ") dodads");
}
catch (Exception e)
{
Log.e(TAG, e.getMessage());
}

runOnUiThread(returnRes);
Log.d(TAG, "Welcome getDodads() done");
}

private class DodadAdapter extends ArrayAdapter
{

private ArrayList dodads;

public DodadAdapter(Context context, int textViewResourceId, ArrayList dodads)
{
super(context, textViewResourceId, dodads);
this.dodads = dodads;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
View v = convertView;

if (v == null)
{
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.dodad_row, null);
}

Dodad dodad = dodads.get(position);
if (dodad != null)
{
TextView line1 = (TextView) v.findViewById(R.id.textDodadLine1);
if (line1 != null)
{
line1.setText(dodad.getName());
}

TextView line2 = (TextView) v.findViewById(R.id.textDodadLine2);
if(line2 != null)
{
line2.setText(dodad.getDescription());
}
}

return v;
}
}
}

No comments:

Post a Comment