views:

92

answers:

2

I've got a quite interesting issue when I try to display a ProgressDialog (the simple, spinner type) within a onPreferenceChange listener.

public class SettingsActivity extends PreferenceActivity {
  private ProgressDialog dialog;

  public void onCreate(Bundle savedInstanceState) {
    ListPreference pref= (ListPreference) findPreference("myPreference");  
    pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

      @Override
      public boolean onPreferenceChange(Preference preference, Object newValue) {
        dialog = ProgressDialog.show(SettingsActivity.this, "", "Doing stuff...", true);
        SystemClock.sleep(2000);
     }
    return true;
  }
}

The ProgressDialog shows up, but not until the method (sleep in this case) has finished. What am I doing wrong?

+1  A: 

You're sleeping on the main UI thread, which stops the operating system from handling your application's events. This will stop your app from redrawing and as you discovered, can prevent new windows from actually appearing.

Instead of sleeping, try this:

final ProgressDialog dialog = ProgressDialog.show(
    SettingsActivity.this, "", "Doing stuff...", true);
new Handler().postDelayed(new Runnable() {
    public void run() {
      dialog.hide();
    }
  }, 2000);
dmazzoni
Thank you for telling me what the problem was, since I rather thought it had something to do with the PreferenceActivity (since this problem for some reason hasn't occured in any other of my activities). However, since I would like to be able to call other methods than sleep() in the future, it wouldn't be a very good solution (even though it probably would've been the best solution otherwise).
nico
A: 

You can use AsyncTask to run the function in a separate thread (see http://developer.android.com/resources/articles/painless-threading.html)

This is probably a bit unnecessary if you just want to invoke a sleep method, but should work even for other methods that otherwise would block the UI thread.

You could do something like this:

private class BackgroundTask extends AsyncTask<Integer, Integer, void> {
    private ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = ProgressDialog.show(SettingsActivity.this, "", "Doing stuff...", true);
    }

    @Override
    protected void doInBackground(Integer... params) {
        sleep(params[0]);
    }

    @Override
    protected void onPostExecute(Boolean result) {
        dialog.dismiss();
    }
 }

And than call it using the code below:

new BackgroundTask().execute(2000);
nico