How to show ProgressDialog across launching a new Activity?
Asked Answered
F

3

9

Goal: Have a ProgressDialog which shows "Loading..." until next Activity is completely loaded and shown on screen.

Tried with ProgressDialog context and activity set to originating Activity. Also tried with getApplicationContext() and getParentContext(). Exceptions on the last two approaches. Need to do this as destination Activity is slow to render due to non-simple Layout file. (Cannot fix that right now due to organizational issues.) Turns out the destination Activity takes 1-2 seconds to OnCreate and then screen goes black for up to 5+ seconds then it paints. The rendering is just slow. Did review with Hierarchy Viewer and see lots of red balls but can't fix now.

Read up on some related but haven't found a fix. E.g. What's the difference between the various methods to get a Context?

E.g. both of these crash. Using the "this" of source Activity doesn't work either.

// Context parentContext = this.getParent().getBaseContext();    
Context parentContext = this.getApplicationContext();
ProgressDialogMenuable theProgressDialog = new ProgressDialogMenuable(parentContext,this);
theProgressDialog.setTitle("yeeha");
theProgressDialog.setMessage("weewah");
theProgressDialog.setIndeterminate(true);
theProgressDialog.setCancelable(true);
theProgressDialog.show();

Also, oddly, nothing happens when I do this: theProgressDialog.show(); ActivityHelper.changeActivity(this, v, InsMyHoldingsActivity.class, extraMap, -1, -1); User clicks button to show next activity but the ProgressDialog conflicts with the Activity launch and nothing actually happens other than the button becoming yellow ontouch. Button below works. removing ProgressDialog creation and it works. No console messages logged. A little offputting to the developer for sure.

Fiche answered 22/10, 2012 at 18:7 Comment(6)
Create an async task in Your new activity, do all the processing there, set layout elements in post execute. Show progress bar in on create, and dismiss in post execute.Appetizer
Let me try that. Situation where I can only subclass (not change) destination Activity. So, this might work.Fiche
If you post as solution then I'll accept. I don't think the ProgressDialog can span Activities' lifecycles (more than one Activity); but one can effect it to the user with this approach One PDlg in Activity A and then another in ActivityB like you said. I actually used a different syntax than the AsynTask but semantically its the same I believe. final Runnable r = new Runnable() { public void run() { setupActivityDisplay(); // thig that takes a while theProgressDialog.dismiss(); } }; (new Handler()).postDelayed(r, 1000);Fiche
More research suggests there is no way to show a ProgressDialog prior to the Activity Layout being completed. Simply put, with a complex layout, the user will see a black (blank) screen for some time. Still researching.Fiche
There is a way to show the ProgressDialog. After onCreate. Just remove the layout setContentView( call from onCreate. Do it later.Fiche
Moving the setContentView( call to onStart did not help. In fact, seems onResume needs to be completed before the layout is ever applied. ProgressDialog will not come up either; so, AsyncTask is the way to make it work best.Fiche
A
12

You can show a progress dialog like this -

Define this

private ProgressDialog pd = null;

in your activity class

Put this in your onCreate (Dont setContentView directly here)

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.pd = ProgressDialog.show(this, "Fancy App",
                    "Loading...Please wait...", true, false);
        // Start a new thread that will download all the data
        new IAmABackgroundTask().execute();

    }

// Background heavy lifting

class IAmABackgroundTask extends
        AsyncTask<String, Integer, Boolean> {
    @Override
    protected void onPreExecute() {
        // showDialog(AUTHORIZING_DIALOG);
    }

    @Override
    protected void onPostExecute(Boolean result) {

        // Pass the result data back to the main activity
        ActivityName.this.data = result;

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

        setContentView(R.layout.main);


    }

    @Override
    protected Boolean doInBackground(String... params) {

        //Do all your slow tasks here but dont set anything on UI
                    //ALL ui activities on the main thread 

        return true;

    }

}

Also go through this :http://developer.android.com/training/improving-layouts/index.html for optimizing layout performance. Also Use Traceview to look for bottlenecks

Appetizer answered 23/10, 2012 at 9:0 Comment(2)
This is the correct approach. Delay the slow rendering until later. Had to do with AsyncTask as "post" with Handler did not work (suspect AsyncTask is only run from MessageQueue if nothing else? haven't found out.) I actually needed two AsycTasks. One to set the layout and then the second one populates with data. Thanks for the posting Slartibartfast.Fiche
No problem. Please accept as answer if it solved your problem and welcome to SO :)Appetizer
L
3

There is two ways to

First approach To use Async Task

If you are doing heavy tasks eg loading data from server or parsing xml in that case use AsynTask<> If you want to call ActivityB from ActivityA then

*step-1*create a AsyncTask class. write all background tasks inside doBackground() method and after completion of task you want to call an activity that code write inside onPostExecute() post execute method

import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.view.View;



public class LoadingDataFromServer extends AsyncTask {
    Context currentContext = null;

    boolean isCancelled = false;


    public LoadingDataFromServer(Context context) {
        currentContext = context;

    }

    @Override
    protected void onPreExecute() {
        if (DashboardActivity.progressBarLayout != null) {
            DashboardActivity.progressBarLayout.setVisibility(View.VISIBLE);
            // Log.i(TAG,".....Now make progress bar visible.....");
        }

        super.onPreExecute();
    }

    @Override
    protected Object doInBackground(Object... params) {
        // do background processing

        try {
// do background tasks eg sever communication
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Object result) {
        // TODO Auto-generated method stub
        // progressDialog.dismiss();

        // call second Activity
        Intent i = new Intent(currentContext, com.ActvityB.class);
        super.onPostExecute(result);
    }

    @Override
    protected void onCancelled() {
        // TODO Auto-generated method stub
        isCancelled = true;
        super.onCancelled();
    }

}

step-2 In the activity fro where you want to jump to new activity (eg in ActivityA) call the execute() of AsynTask

new LoadingDataFromServer(context).execute(null);

Second approach

First show progress dialog. create a thread to do all background tasks. when the thread completes the task then cancel the progress dialog and call the next activity

or

when thread complets the task then call next activity pass this object (progress dialog) and inside that new activity dismiss this dialog.

Lunarian answered 23/10, 2012 at 6:51 Comment(3)
Accepting this answer as the best approach. In reality, the layout rendering step is a black hole (and black screen) to the developer. One cannot show a ProgressDialog across two Activities from the research I have done. Similar questions and nobody has found a way. #6564031 and #4144580. Process: 1-user touch, new Activity object 2s. 2-Rendering layout 5s. 3-Data Retrieval 0s. 4-UI Population 2s. In emu.Fiche
Looks like it may be possible with an ActivityGroup but that is deprecated now. developer.android.com/reference/android/app/ActivityGroup.htmlFiche
Did the layout rendering in an AsyncTask as first poster told me to do. It works.Fiche
M
0

Here is my code that can help.

In this, I'm only posting the first method of AsyncTask i.e onPreExecute.

User_AsyncTask extends AsyncTask:

public class User_AsyncTask extends AsyncTask<String, String, String>
    {
        String response = "";

        @Override
        protected void onPreExecute()
        {
            try
            {
                if (progressDialog != null)
                    progressDialog.cancel();
            }
            catch (Exception e)
            {

            }
            progressDialog = ProgressDialog.show(DisplayDetails.this, "", "Please wait...", true, true);
            progressDialog.setCancelable(false);
            progressDialog.show();
        }
Michel answered 9/12, 2016 at 7:54 Comment(1)
plz rate this answer if its helpfullMichel

© 2022 - 2024 — McMap. All rights reserved.