Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show ProgressDialog while loading layout with setContentView

this is my scenario: I've got a login screen that opens another activity. In the Activity I simply have:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);
}

The layout is kind of heavy, cause it is made of some fragments, and takes about 1.5 seconds to load. Now, how can I display a ProgressDialog while setContentView finishes inflating the layout? I've tried with AsyncTask by putting the setContentView in the doInBackground, but of course that cannot be done, as the UI can be updated from the UI thread only. So I need to call setContentView in the UI thread, but where do I have to show/dismiss the ProgressDialog?

I appreciate your help.

Fra.

EDIT: I followed @JohnBoker's previous suggestion, this is the code I have now:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_empty_layout);
    new ContentSetterTask().execute("");
}

private class ContentSetterTask extends AsyncTask<String, Void, Void> {

    public ProgressDialog prgDlg;

    @Override
    protected void onPreExecute() {
        android.os.Debug.waitForDebugger();
        prgDlg = ProgressDialog.show(MultiPaneActivity.this, "", "Loading...", true);

    }

@Override
protected Void doInBackground(String... args) {
    android.os.Debug.waitForDebugger();
    ViewGroup rootView = (ViewGroup)findViewById(R.id.emptyLayout);
    LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View inflated = inflater.inflate(R.layout.activity_details, rootView);
    return null;
}

@Override
protected void onPostExecute(Void arg) {
    android.os.Debug.waitForDebugger();
    if (prgDlg.isShowing())
        prgDlg.dismiss();
    }
  }
}

The row

View inflated = inflater.inflate(R.layout.activity_details, rootView);

gives me the error:

06-27 16:47:24.010:   
ERROR/AndroidRuntime(8830): Caused by:android.view.ViewRoot$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views.
like image 789
frapontillo Avatar asked Jun 27 '11 13:06

frapontillo


2 Answers

I decided to make a full answer here for future readers.

After several hours spent on the issue, I realized that the issue is I'm trying to do two things:

  1. inflating a layout, which is an operation that NEEDS to be made on the UI thread by design.
  2. showing a Dialog (ProgressDialog, actually, but this does not change the outcome), that can be done from the UI thread only, since Services can't show any Dialog.

So, as both calls are made from the UI thread (onCreate or AsyncTask makes no difference, it's still the UI thread), the first blocks the second one from showing up appropriately. Bottom line is: this problem can't be solved in Android right now. Let's hope we can get some better APIs for interacting with the UI, because the ones we've got kind of suck.

I'm going to solve this problem by changing the layout and making it lighter (if possible!). Thanks everyone!

like image 148
frapontillo Avatar answered Sep 21 '22 19:09

frapontillo


I had the same issue when creating a heavy view, what I did was put a linearlayout only in the xml file and called the setContentView on that, then i created the real view in the asynctask and added the view dymanically to the linearlayout.

This method seems to work and i was able to put a progress dialog up during the process.

like image 28
John Boker Avatar answered Sep 24 '22 19:09

John Boker