0
votes

I need to write static method that shows ProgressDialog, runs worker in thread and after worker finished ProgreesDialog must dismiss and my method return what worker did. This is my code:

public static  TOut execute(final Context c, final String title, final String message, final IProgressWorker  worker, final TIn param)
{

        final ValueHolder result = new ValueHolder();
        final ProgressDialog progress=new ProgressDialog(c,R.layout.progress_impl_layout);
        Thread main = new Thread(new Runnable(){
            @Override
            public void run() {
                Looper.prepare();//creating new Looper to show progressDialog immediately 
                final Looper looper=Looper.myLooper();
                AsyncTask async = new AsyncTask(){
                    @Override
                    protected void onPostExecute(Boolean result) {
                        super.onPostExecute(result);
                        isDone=true;
                        looper.quit();//quit Looper.loop
                        progress.dismiss();
                    }
                    @Override
                    protected void onPreExecute() {
                        super.onPreExecute();
                        progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                        progress.setTitle(title);
                        progress.setMessage(message);
                        progress.show();
                    }

                    @Override
                    protected Boolean doInBackground(Integer... params) {
                        IProgressImpl progressImpl=new MyProgressImpl(progress);
                        worker.execute(progressImpl, param);
                        return true;
                    }
                };

                async.execute(0);
                if(!isDone){
                    Looper.loop();//show progressDialog immediately
                }
            }
        });
        main.start();
        try {
            main.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return result.value;
    }

Everything works, but ProgressDialog does not dismissing. I suspect that looper.quit() do something bad, but I need to stop Looper.loop(). I call loop() because i need to show ProgressDialog immediately.

2

2 Answers

1
votes

How to Update the Android UI in an AsyncTask

Instead of using the Looper in your AsyncTask I recommend that you use Activity.runOnUiThread() to update the UI for methods of your ProgressDialog such as show() and dismiss().

Example:

runOnUiThread(new Runnable() {
    @Override
        public void run() {
        progress.dismiss();       
    }
});

If your Context c, above, is an Activity context, you can use it to access runOnUiThread():

    c.runOnUiThread()...

You may have to make an Activity available to your processing class via various methods such as passing it into your execute() method or using an Android Application instance.

Otherwise, you can use a regular Context, but the same Runnable above will have to execute in a Thread or Task.

0
votes

First of all, the thread stored into the main variable is not the main (a.k.a. UI) thread.

As to runOnUIThread(), you can have a Handler created on the UI thread, post(Runnable r) and postDelayed(Runnable r, long delayMillis) will replace runOnUIThread(). [Alternatively, your function already does have a Context parameter; you could require it to be an Activity.]

Note also that in Android 2 initializing the AsyncTask class on the thread other than the UI thread leads to an error.

Finally, why do you need a separate thread if you are using AsyncTask? Or why AsyncTask if you already have a worker thread? You definitely do not need both of them.