20

I have a ListActivity which launches another Activity based on the list selection. This second Activity needs to load a fair bit of data from the internet and as such there is a noticeable delay between when the user clicks on an item and when the Activity displays.

This is a problem because I currently have no way to indicate to the user that their click is being processed (even just changing the colour of the selected list item would be sufficient but I can't find a good way to do that). Ideally I'd be able to display an indeterminate ProgressDialog while the second Activity is loading.

I've tried a few different approaches for this but nothing seems to work as desired.


I've tried the following:

  • Retrieving the serializable data (not all of it but some part) in an AsyncTask in the first Activity and passing it as an extra to the second. This didn't really work well as a ProgressDialog I created in onPreExecute() didn't display immediately (it seems delayed by the processing done in doInBackground() for some reason.)

Here is the code for that:

AsyncTask<String, Void, String> read = new AsyncTask<String, Void, String>() {
    Dialog progress;

    @Override
    protected void onPreExecute() {
        progress = ProgressDialog.show(SearchActivity.this, 
                "Loading data", "Please wait...");
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(String... params) {
        DatasetReader reader = new DatasetReader();
        reader.setFundID(params[0]);
        reader.addDatsets(FundProfile.datasets);
        reader.populate();
        return reader.toString();
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        progress.dismiss();
    }
};
read.execute(selectedItem.getUniqueID());
try {
    action = new Intent(SearchActivity.this, FundProfile.class);
    action.putExtra("data", read.get());
} catch(Exception ex) {
    ex.printStackTrace();
}
  • In the second Activity's onCreate() method (this does not work at all):

    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setProgressBarVisibility(true);

Here is the onCreate() method for the second approach:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setTitleColor(Color.WHITE);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setProgressBarVisibility(true);

    try {
        setContentView(R.layout.fund_profile);
        // init some data
        setProgressBarVisibility(false);
    } catch(Exception ex) {
        FundProfile.this.finish();
    }
}
Octavian Helm
  • 39,405
  • 19
  • 98
  • 102
Adam
  • 417
  • 2
  • 6
  • 18
  • 1
    Which different approaches have you tried? Could you share your attempts? – Cristian Feb 01 '11 at 19:09
  • I'm surprised the first approach didn't work. A `ProgressDialog` shown in `onPreExecute()` should not be held up by the code in `doInBackground()`, perhaps there was some other issue with your code? – dave.c Feb 01 '11 at 19:35
  • Possibly? I added the relevant code.. – Adam Feb 01 '11 at 20:45

3 Answers3

16

If you have long operations you should not be doing them in onCreate in any case as this will freeze the UI (whether or not the activity is displayed). The UI set by onCreate will not appear and the UI will be unresponsive until after the onCreate call finishes.

It seems you can start your second activity and display a progress bar (or requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);), then start an ASyncTask which will be responsible for updating your UI once data has been retrieved.

Damp
  • 3,328
  • 20
  • 19
  • Yeah, I figured that's the proper way to do it (load data in another thread), but I wanted to avoid it for now.. but I bit the bullet and did it this way (AsyncTask makes this less painful than it could have been..) – Adam Feb 02 '11 at 21:18
3

Adam,

It sounds like you are looking for the Indeterminate Progress bar: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.html

You can display this while you are loading your second Activity then set the visibility to false once the second Activity has loaded its data.

Will Tate
  • 33,439
  • 9
  • 77
  • 71
  • The first activity's view stays on the screen until the entire onCreate() method completes, so I never see a progress bar. – Adam Feb 01 '11 at 19:44
  • when are you calling `setContentView()` in your `onCreate()` method? – Will Tate Feb 01 '11 at 19:45
  • First thing after (supposedly?) showing the progress bar. I've updated the original post with this info. – Adam Feb 01 '11 at 19:50
  • well, it looks like your setting the progress bar to visible then immediately after setting it back to invisible. – Will Tate Feb 01 '11 at 19:58
  • I commented out some code which retrieves the data and populates the views (actually, I created some custom views which populate their own data..) – Adam Feb 01 '11 at 20:02
3

Move creating the Intent -- and really anything you need to do after the AsyncTask completes -- into onPostExecute:

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    progress.dismiss();
    Intent action = new Intent(SearchActivity.this, FundProfile.class);
    action.putExtra("data", result);
    // ... do more here
}

The problem is that AsyncTask.get() blocks until the task is completed. So in the code above, the UI thread is blocked and the ProgressDialog is never given a chance to appear until the task completes.

Mike
  • 2,422
  • 23
  • 14