开发者

How can I show a Progress dialog between two activities?

I have a problem. I need to go from one activity to anoth开发者_如何转开发er. My second activity has a big xml layout, with a lot of elements (I'm speaking about four hundred aprox.), then it takes a few seconds (too much) to show this second Activity.

How can I show a Progress dialog between two activities?

I'm trying to use a background task to do this.

I have this method in my Activity A:

  private void goToYear() {
   Intent intent = new Intent();
   intent.setClass (getBaseContext(), YearActivity.class);
   startActivity( intent);
  }

And in my Activity B:

public class YearActivity extends Activity {

 private String  TAG = "YearActivity ::";

 private ProgressDialog pd = null;


    @Override
    public void onCreate( Bundle savedInstanceState) {
        super.onCreate( savedInstanceState);

        // Show the ProgressDialog on this thread
        this.pd = ProgressDialog.show(this, "Working...", "Calculating the screen...", true, false);

        // Start a new thread that will download all the data
        new MakeYearTask().execute();

    }

    private void initCalendar () {
      this.setContentView( R.layout.calendar_year);   

   ...
   ...
   initialize values
   ...
   ...

    }


    private class MakeYearTask extends AsyncTask<String, Void, Object> {
        protected Void doInBackground(String... args) {
            Log.i("YearActivity::MakeYearTask", "MakeYearTask Background thread starting");

   YearActivity.this.initCalendar();


        }

        protected void onPostExecute(Object result) {

            if (YearActivity.this.pd != null) {
             YearActivity.this.pd.dismiss();
            }
        }
   } 
}

You can see that I make the setContentView out of the onCreate method.

This doesn't work. It gives me one exception, like this:

12-09 19:49:17.729: ERROR/AndroidRuntime(218): java.lang.RuntimeException: An error occured while executing doInBackground()
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:234)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:258)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.FutureTask.run(FutureTask.java:122)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:648)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:673)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.lang.Thread.run(Thread.java:1060)
12-09 19:49:17.729: ERROR/AndroidRuntime(218): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.view.ViewRoot.checkThread(ViewRoot.java:2629)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.view.ViewRoot.requestLayout(ViewRoot.java:545)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.view.View.requestLayout(View.java:7657)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.view.ViewGroup.addView(ViewGroup.java:1749)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.view.ViewGroup.addView(ViewGroup.java:1731)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at com.android.internal.policy.impl.PhoneWindow.generateLayout(PhoneWindow.java:2186)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at com.android.internal.policy.impl.PhoneWindow.installDecor(PhoneWindow.java:2239)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:309)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.app.Activity.setContentView(Activity.java:1620)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at es.jota.app.YearActivity.initCalendar(YearActivity.java:42)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at es.jota.app.YearActivity.access$0(YearActivity.java:41)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at es.jota.app.YearActivity.initCalendar$MakeYearTask.doInBackground(YearActivity.java:120)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at es.jota.app.YearActivity.initCalendar$MakeYearTask.doInBackground(YearActivity.java:1)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:256)
12-09 19:49:17.729: ERROR/AndroidRuntime(218):     ... 4 more


This is poor design to start with. If you have such a large amount of data to present to the user which would presumably be scrolled through, you should instead use an AdapterView subclass, such as a ListView or GridView. An XML layout with almost 400 elements is incredibly large.

I understand what you're trying to do (you're attempting to perform the lengthy building of the massive View hierarchy on a separate Thread using an AsyncTask, but what you've found is that it's blown up on you for trying to touch the View hierarchy on a non-UI Thread).

Even if you did manage to implement some kind of progress bar in the foreground while the hierarchy is being built, I'm not sure if the system would provide the means to call back progress information while it inflates the View hierarchy (but I may be wrong).

AdapterViews were created to solve exactly this kind of problem. With an AdapterView, typically only a screen's worth of Views exist in memory at any time. For example, you could have a table with a thousand rows, but with only seven rows fitting onto the screen at once, only eight row Views might exist in memory at once. Furthermore, the adapter should also recycle the Views, further optimising performance.


This may not be the best solution but what you can do is extend the basic Theme used in android and set the window background to an image that indicates the activity is loading. Then set that theme to Activity B. Now while Activity B is loading it will show your drawable instead of the black window. You may even be able to get creative with an animation-list and get some kind of indeterminate loading effect.


Have you tried doing new MakeYearTask().execute(); in onResume() instead?

While not elegant you could fire a delayed thread post in on create to wait for a couple of millis.

Edit:

I just this error:

(Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views)

are you modifying the UI from the AsyncTask?

You should just build the data in doInBackground(), but update the ui in onPostExecute().


Your formatting is a little off, but if I understand correctly, you are calling initCalendar() in your AsyncTask's doInBackground(). You are not allowed to do that with AsyncTasks.

Use doInBackground() for long-running operations such as HTTP calls, DB accesses, etc. Once you have the stuff you need, call initCalendar() from onPostExecute().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜