javaandroidandroid-asynctaskprogressdialog

How to show spinning progress dialogue with using separate Async Task Class


In my app, i'm reading text files from web server using Async Tasking from a separate class because it is used in many activities, so i've made a dedicated class. I'm trying to show a spinning progress dialogue but it is giving me error when i put the code in Async Tasking class.

here is my cod for Async Task Class

public class Utilssss extends AsyncTask<String, String, String> {
    private Context         mContext;
    private ProgressDialog  pdia;

    // constructor
    public Utilssss(Context activityContext) {
        mContext = activityContext;
    }

    protected void onPreExecute() {
        super.onPreExecute();
        pdia = new ProgressDialog(mContext);
        pdia.setMessage("Loading...");
        pdia.show();
    }

    protected String doInBackground(String... url) {
        return GetLinkss(url[0]);

    }

    protected void onPostExecute(String result) {
        // Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
        super.onPostExecute(result);
        pdia.dismiss();
    }

    private String GetLinkss(String url) {

        // your stuff
        String StringBuffer = "";
        String stringText = "";
        try {
            URL link = new URL(url);
            BufferedReader bufferReader = new BufferedReader(new InputStreamReader(link.openStream()));

            while ((StringBuffer = bufferReader.readLine()) != null) {
                stringText += StringBuffer;
            }
            bufferReader.close();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return stringText;
    }

}

Code how i'm accessing this class

public void urdu(View view) throws InterruptedException, ExecutionException {
        String fileexist = null;

        fileexist = new Utilssss(getBaseContext()).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt").get();

        Toast.makeText(getBaseContext(), fileexist, Toast.LENGTH_SHORT).show();

        // if (fileexist != 229) {
        Intent i = new Intent(getBaseContext(), MainPage.class);
        i.putExtra(LANGUAGE, "urdu");
        startActivity(i);

Here is the LogCat results.

12-05 00:38:06.266: E/AndroidRuntime(28766): FATAL EXCEPTION: main
12-05 00:38:06.266: E/AndroidRuntime(28766): java.lang.IllegalStateException: Could not execute method of the activity
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View$1.onClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View.performClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View$PerformClick.run(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Handler.handleCallback(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Handler.dispatchMessage(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Looper.loop(Looper.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.app.ActivityThread.main(ActivityThread.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at dalvik.system.NativeStart.main(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: java.lang.reflect.InvocationTargetException
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    ... 12 more
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.ViewRootImpl.setView(ViewRootImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.app.Dialog.show(Dialog.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at md.literature.imranseries.Utilssss.onPreExecute(Utilssss.java:35)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.AsyncTask.executeOnExecutor(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.AsyncTask.execute(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at md.literature.imranseries.Selection.urdu(Selection.java:65)
12-05 00:38:06.266: E/AndroidRuntime(28766):    ... 14 more

Just one more thing i want to ask. Sorry to bother you guys again.. Here is the thing, one of my activity relies on the results of Asynctask and should no proceed unless the task is completed, but this is not happening, here is a sample piece of code which proves it.

        final Context context = this;
        new Utils(context, new Utils.UtilsCallback() {
            @Override
            public void onResult(String lstr) {
//              lstr = string;
                Toast.makeText(getBaseContext(), "Now Raeading" + Novelselected, Toast.LENGTH_LONG).show();
            }
        }).execute(ulti_link + "/" + Novelselected.replace(" ", "%20") + ".txt");

        Toast.makeText(getBaseContext(), "Now Raeading", Toast.LENGTH_LONG).show();

in the above code, the following Toast appears before the Toast within the AsyncTAsk appears, The question is, how can i pause my main thread to wait for the AsyncTAsk to complete. Thanks a lot :)


Solution

  • Besides using the correct Context you must not use AsyncTask#get(). Never. It blocks the Ui thread until the result is available and you can not show a progress dialog during that time then because you are already waiting for the result.

    If you want to use an AsyncTask from a different class add a callback mechanism of your own.

    public class Utilssss extends AsyncTask<String, String, String> {
    
        /** Implement this somewhere to get the result */
        public interface UtilssssCallback {
            void onResult(String string);
        }
    
        private Context mContext;
        private ProgressDialog pdia;
    
        private UtilssssCallback mListener;
    
        // constructor
        public Utilssss(Context activityContext, UtilssssCallback listener) {
            mContext = activityContext;
            mListener = listener; // save callback
        }
    
        @Override
        protected void onPostExecute(String result) {
            pdia.dismiss();
            mListener.onResult(result);
        }
    
        // rest omitted since unchanged
    
    }
    

    And inside your Activity

    public void urdu(View view) {
        final Context context = this;
        new Utilssss(context, new Utilssss.UtilssssCallback() {
            @Override
            public void onResult(String string) {
                Toast.makeText(context, string, Toast.LENGTH_LONG).show();
                Intent i = new Intent(context, MainPage.class);
                i.putExtra(LANGUAGE, "urdu");
                context.startActivity(i);
            }
        }).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
    }
    

    Note that the code inside onResult is executed way after the program flow has already left the urdu(View view) method.


    Alternatively to implementing the callback as an anonymous inner class (new UtilssssCallback(){...}) you could also let the Activity implement the interface and make it a method. Doing it that way looks less confusing but is essentially the same.

    public class TheActivity extends FragmentActivity implements UtilssssCallback {
    
        public void urdu(View view) {
            // those two are not necessary but help make it obvious what parameters we have
            Context context = this;
            UtilssssCallback callback = this; // the class implements that
            new Utilssss(context, callback).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
        }
    
        @Override
        public void onResult(String string) {
            Toast.makeText(context, string, Toast.LENGTH_LONG).show();
        }
    
    ....