1

In my Activity, I load the content for a list from a DB, and want to display a ProgressDialog while it´s loading.
I got both working on it´s own, but if I load the data in a thread (which I should do?), the list is displayed before it´s data is loaded. But if I use join, the ProgressDialog doesnt even appear.

How can I combine this? Or is this not possible at all with threads? (AsyncTask maybe?)

Here´s the code for reference:

    final ProgressDialog progressD=ProgressDialog.show(ShopSwitchActivity.this, "", "Loading..", true);

    Thread myThread = new Thread(new Runnable() {  
        @Override
        public void run() {
          try
          {
              getData();
          }catch(Exception e){}
        }
    });
    myThread.start();

    try {
            myThread.join();
    } catch (InterruptedException e) {
    }
    progressD.dismiss();

EDIT: Updated Code with AsyncTask:

public class LoadList extends AsyncTask<String, Void, Boolean> {

    ProgressDialog dialog;
    ShopSwitchActivity activity;

    public LoadList(ShopSwitchActivity activity) {
        this.activity = activity;
        dialog = new ProgressDialog(activity);
    }

    protected void onPreExecute() {
        this.dialog.setMessage("Loading...");
        this.dialog.show();
    }

        @Override
    protected void onPostExecute(final Boolean success) {
        if (dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    protected Boolean doInBackground(final String... args) {
        try{
       activity.getData();
        } catch (Exception e) {
            Log.e("error", e.getMessage());
        }
       return true;
    }
}

Edit: My Solution Using AsyncTask now to load the Data, and after it´s done, I refresh the list with the new data.

Benjamin Schwalb
  • 1,124
  • 11
  • 31
  • First take a look here: http://stackoverflow.com/questions/4538338/progressdialog-in-asynctask – g00dy Jul 08 '13 at 13:29

4 Answers4

4

You can do it with AsyncTask. Write AsyncTask class in your main class that you want to do your operations. You can create the progress dialog in preexcecute of your async class and dismiss in onpostexecute of async class. Here is how you will do this:

  class MyAsync extends AsyncTask<String, Void, Void> {
     ProgressDialog pd;
     Context co;
     MyActivity ma;

     public MyAsync (MyActivity ma){
         this.ma= ma;
         this.co = ma;
         pd= new ProgressDialog(co);
     }

     @Override
     protected void onPreExecute() {
         this.pd.show();

     super.onPreExecute();
     }
            @Override
            protected Void doInBackground(String... params) {
                // do your database operations here
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                // show db results and dismiss progress dialog pd.dismiss();
                super.onPostExecute(result);
            }
        }

in MyActivity call as :

MyActivity ma = this;
new MyAsync(ma).execute();
canova
  • 3,965
  • 2
  • 22
  • 39
  • Tried with AsyncTask, see Edited code in my Question. Doesnt work though: "Only the original thread that created a view hierachy can touch it´s views" – Benjamin Schwalb Jul 08 '13 at 13:46
  • I edited my answer and tested it as well. Now it is working as intended. Sorry for the small mistake – canova Jul 08 '13 at 14:11
  • `this.ma= ma; this.co = ma; pd= new ProgressDialog(co);` Why not just `pd = new ProgressDialog(ma);`? – Benjamin Schwalb Jul 08 '13 at 14:18
  • it gets context it's just a habit for me to use context values for progressdialog. This is working the way that you want it to be, I tested it so hope you find this useful. – canova Jul 08 '13 at 14:45
  • The only problem is, that, like I said, I need to wait in the Main/UI-Thread until this Task is finished, without blocking the ProgressDialog. – Benjamin Schwalb Jul 08 '13 at 14:49
1

You seem to miss the point of a thread. A thread occurs at the same time as your application. So your app doesn't call start then wait for the thread to be over- if it did you could just use a function. Instead your code continues to run. So if you just call join immediately, you're not doing anything. You'd get around a NetworkOnMainThreadException this way, but you'd still hold up the UI thread making your app totally non-responsive (and as a result not showing the dialog), and you'd eventually crash when a watchdog timer kills you.

Instead, the best way to handle this is to use an AsyncTask. Call getData in doInBackground(). Then dismiss the dialog in onPostExecute.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • I do know why and how to use a thread, but afaik I can´t use a ProgressDialog without a thread, this is the only reason I wanted to use one. – Benjamin Schwalb Jul 08 '13 at 13:42
  • You can use a progress dialog without a thread. YOu can do it with an async task (which is a thread with some built in functionality for post thread processing on the UI thread), or without any kind of threading at all- just plop one up there. Why did you ever think you needed a thread? – Gabe Sechan Jul 08 '13 at 13:43
  • Also in case I didn't make it clear- by calling join immediately you never get tot he actual drawing code that would draw the progress dialog. That all happens on the UI thread. – Gabe Sechan Jul 08 '13 at 13:44
  • All the tutorials I read (about ProgressDialogs) used a thread/async and most of them (or even all) said that i do need one. Also, I didnt want to block the UI-thread for seconds without any feedback, and if the loading runs in foreground, that´s what happened. – Benjamin Schwalb Jul 08 '13 at 13:46
  • 1
    A ProgressDialog is just a UI element. You can always put one up at any time. Now its frequently easier to use a thread/asyncTask (particularly AsyncTasks), but nothing will ever stop you from displaying a UI element so long as you're on the UI thread. Either you misread the tutorials or they're VERY wrong. – Gabe Sechan Jul 08 '13 at 13:48
  • But if I let all the loading happen directly in the UI-thread, wouldnt it get blocked, thus also not showing the ProgressDialog? (atleast not updating it?) – Benjamin Schwalb Jul 08 '13 at 13:50
  • Your getData function has to happen in another thread or it will block the UI. The progress dialog is just a UI widget- it isn't loading anything. Its just a pretty little circle that goes around and tells people something is happening. It doesn't do any real work. – Gabe Sechan Jul 08 '13 at 13:52
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33084/discussion-between-benjamin-schwalb-and-gabe-sechan) – Benjamin Schwalb Jul 08 '13 at 13:53
1

You should use AsyncTask instead actually.

Here is the link to the library. It is fairly simple:

1) onPreExecute() = show ProgressDialog

2) doInBackground() = execute your code

3) onPostExecute() = dismiss ProgressDialog

Here's a nice tutorial too.

In general:

@Override
protected void onPreExecute() {
    dialog = new ProgressDialog(this.context);
    dialog.setMessage("Loading...");
    dialog.setCanceledOnTouchOutside(false);
}

@Override
protected void onPostExecute(String result) {
    if(dialog.isShowing()) {
        dialog.dismiss();
    }
}
g00dy
  • 6,752
  • 2
  • 30
  • 43
1
private Thread myThread;
private ProgressDialog mProgDialog;

mProgDialog = ProgressDialog.show(ShopSwitchActivity.this,"","Laden..", true);

myThread= new Thread(new Runnable() 
{
    public void run() 
    {
    myThread.setPriority(Thread.MIN_PRIORITY);

    try
    {
        getData();
    }catch(Exception e){}

    runOnUiThread(new Runnable() 
    {
        public void run() 
        {
        if (mProgDialog != null&& mProgDialog.isShowing())
        mProgDialog.dismiss();
        }                                                                               }
    });

    }
});
myThread.start();
user2060635
  • 251
  • 1
  • 5