How can I show a Progress dialog between two activities?
Asked Answered
N

4

11

I have a problem. I need to go from one activity to another. 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
Nessim answered 9/12, 2010 at 20:29 Comment(1)
Answer how to create progress bar between two activity linkPeterec
J
1

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.

Johnnyjohnnycake answered 2/4, 2013 at 18:0 Comment(4)
And what if you need to design a screen that holds a table that should be scrolled horizontally and vertically, how would you solve that using an adapter?Griselgriselda
Good point. I briefly searched and found several SO questions which suggest a horizontally and vertically scrollable adapter-based layout is possible with a little bit of work (e.g. #7682081). I think if the OP is experiencing an excessive delay during inflation in .setContentView() then overall performance likely to be sluggish (perhaps on slower devices) so therefore using an adapter-based layout is worthwhile, even if it means a bit of pain to make it work, or rethinking the UI a little.Johnnyjohnnycake
Actually I agree, I only had this problem here: #15560351 and still searching for a solution. But thanks : )Griselgriselda
Aaah! That's interesting - as it happens, I actually starred and upvoted that very question of yours the other day. An application of my own also has a very similar UI structure (pager with Fragments containing TableLayouts, in a situation where using an adapter is tricky) and it is quite sluggish at times, so I was quite interested in seeing what suggestions had been given to you. I'll be sure to feed back any help I can give.Johnnyjohnnycake
T
0

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.

Tetragon answered 9/12, 2010 at 20:40 Comment(3)
Mmmm. I think like you, but if it works, it will be ok for me :) I'm going to try that, and I tell you what happend. Thanks.Nessim
I don't try this yet, but I put in my "to do" list. When I try this, I tell you the result. Thanks!Nessim
looking forward to hearing/seeing the resultsTetragon
D
0

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().

Dressel answered 9/12, 2010 at 21:3 Comment(2)
Yes, right now, with the same result. :( Thanks in any case.Nessim
Edited my answer with aditional info. Maybe its that.Dressel
P
0

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().

Povertystricken answered 10/12, 2010 at 9:43 Comment(4)
Sorry by the format. I fix it :D I going to try to understand your answer. I'm spanish and my english is not so good.Nessim
Basically, what I'm saying is move this YearActivity.this.initCalendar(); to the onPostExecute() method, and I'm trying to explain why. :)Povertystricken
Hi Zarah! It's dificult to explain to me. If I put the YearActivity.this.initCalendar(); on the onPostExecute(), I don't have any error, but the ProgressDialog don't is showing... The transition between activities takes a few seconds, and this is the thing I want prevent. I want show the progressdialog to make the wait more confortable. Do you know what I mean? It's for this reason that I use the AsyncTask. Perhaps another way to do this exists, but I don't know. :(Nessim
Show your progress bar in onPreExecute() and dismiss it on onPostExecute().Povertystricken

© 2022 - 2024 — McMap. All rights reserved.