views:

63

answers:

1

alt text

Hi folks,

So I'm putting the finishing touches on an application and there's still one outstanding issue with the application as a whole.

I display loading indicators in the form of ProgressDialogs while pulling data down from the web. For some reason or another, my ProgressDialogs are appearing to be nested inside of another blank dialog box. The result is tacky.

My layout code looks like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/Theme.MyTheme.EpisodeList">
    <ImageView android:src="@drawable/featured"
        android:layout_width="fill_parent"
        android:layout_height="50sp"
        android:layout_gravity="top"
        android:shadowRadius="0"
        android:shadowColor="#FFFFFF"
        android:id="@+id/header_image"
     />
   <ListView android:id="@+id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
   />
</LinearLayout>

The code I use to display the ProgressDialog is the following:

// In my class definition
private ProgressDialog p;

// in my onCreate method
p = new ProgressDialog(EpisodeActivity.this, ProgressDialog.STYLE_SPINNER);
p.setMessage("Loading...");
p.show();

From the looks if it, there's nothing that seems amiss. I'm also attaching a photo to illustrate the problem.

Any help is appreciated!

+1  A: 

After a few days of futzing around, I figured out the best way to handle ProgressDialogs. Dealing with simple ProgressDialogs is definitely over-complicated on the Android platform, but that doesn't mean we have any excuse to not work with them. Hopefully it will get better (along with the documentation) going into the future. Here are my best practices.

The nesting issue of a ProgressDialog inside a blank Dialog seems to be an issue of pre-2.0 code being run on a 2.1 or 2.2 system. I can only guess that the show() method is also calling super.show(), which behaves differently on 2.1 and 2.2.

So, I've found that it works best if you don't call show() directly on the ProgressDialog objects. Instead, use the built in showDialog() and onCreateDialog() methods to juggle dialogs. Here's a code snippet:

private static final int ID_DIALOG_LOADING = 0;

@Override
protected void onCreate(Bundle tedBundy) {
    // Do stuff

    showDialog(ID_DIALOG_LOADING);

    // Do more stuff in a thread
}

@Override
public void run() {
  // Do some stuff in this thread
  handler.sendEmptyMessage(0);
}

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // Let adapters know the data under them have changed

        try {
            dimissDialog(ArticlesList.ID_DIALOG_LOADING);
            removeDialog(ArticlesList.ID_DIALOG_LOADING);
        } catch (Exception e) {}
    }
}

@Override
protected Dialog onCreateDialog(int id) {
    if (id == ID_DIALOG_LOADING) {
        ProgressDialog loadingDialog = new ProgressDialog(this);
        loadingDialog.setMessage("Loading...");
        loadingDialog.setIndeterminate(true);
        loadingDialog.setCancelable(true);
        return loadingDialog;
    }

    return super.onCreateDialog(id);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    try {
        Log.i("ArticlesList.onSaveInstanceState", "Chirp chirp");
        dismissDialog(ArticlesList.ID_DIALOG_LOADING);
        removeDialog(ArticlesList.ID_DIALOG_LOADING);
    } catch (Exception e) {

    }

    super.onSaveInstanceState(outState);
}

@Override
protected void onDestroy() {
    try {
        dismissDialog(ArticlesList.ID_DIALOG_LOADING);
        removeDialog(ArticlesList.ID_DIALOG_LOADING);
    } catch (Exception e) {

    }

    super.onDestroy();
}

@Override
protected void onPause() {
    try {
        dismissDialog(ArticlesList.ID_DIALOG_LOADING);
        removeDialog(ArticlesList.ID_DIALOG_LOADING);
    } catch (Exception e) {

    }

    super.onPause();
}

@Override
public void onDetachedFromWindow() {
    try {
        dismissDialog(ArticlesList.ID_DIALOG_LOADING);
            removeDialog(ArticlesList.ID_DIALOG_LOADING);
    } catch (Exception e) {

    }

    super.onDetachedFromWindow();
}

This is a long code snippet. You will also see bunches of duplicated code that is constantly trying to kill that dialog dead. This is done because Android will destroy and then re-create a View whenever the phone is rotated. Hopefully in future versions, the window won't be completed destroyed and reloaded whenever the user rotates the screen, and instead implement a onScreenRotate() method.

After trying a few different ways, this hacky solution seems to be the only thing that delivers consistent, speedy results of removing the ProgressDialog. Hope this saves a few days of someone's time in the future.

Kelly Sutton