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.