0

I was trying to show a ProgressDialog in an AsyncTask, but I was getting the error Can't create handler inside thread that has not called Looper.prepare(). So I searched for it and found here that someone had this problem before.

I took the second answer you can see in there and implemented my AsyncTask that way. Everything is good now, but I guess there must be some better way to display that dialog.

This it my AsyncTask after I fixed it

private class MyAsyncTask extends AsyncTask<Void, Void, ArrayList</*SomeObject*/>> {
    ProgressDialog mDialog;

    private MyAsyncTask() {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                mDialog = new ProgressDialog(getActivity());
            }
        });
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mDialog.setMessage("AsyncTask is starting...");
                mDialog.show();
            }
        });
    }

    @Override
    protected ArrayList</*SomeObject*/> doInBackground(Void... params) {
        // some non UI related code...
    }

    @Override
    protected void onPostExecute(ArrayList</*SomeObject*/> someObjects) {
        super.onPostExecute(exams);
        // some code...
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mDialog.dismiss();
            }
        });
    }
}

My questions are

  1. Is there a better way to display the dialog?

  2. Why I get the errors only in this particular AsyncTask? (the code below works well)

I run the AsyncTask you can see below a hundred times and it never crashed, whereas the first one never executed successfully. There must be something I can't see!

private class MyAsyncTask extends AsyncTask<String, Void, String> {
    private final ProgressDialog dialog = new ProgressDialog(mContext);

    private LoginConnectTask() {
    }

    protected void onPreExecute() {
        super.onPreExecute();
        dialog.setMessage("aMessage");
        dialog.show();
    }

    protected String doInBackground(String... strings) {
        return fancyFunction(strings[0], strings[1]);
    }

    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s != null) {
            Toast.makeText(mContext, s, Toast.LENGTH_LONG).show();
        }
        dialog.dismiss();
    }
}
Community
  • 1
  • 1
doplumi
  • 2,938
  • 4
  • 29
  • 45
  • error usually happens when you update ui from a non ui thread – Raghunandan Dec 26 '13 at 19:04
  • are you calling the asynctask from the main thread? – rachit Dec 26 '13 at 19:06
  • but why they don't happen always... I run the AsyncTask you can see below a hundred times and it never crashed, whereas the first one never executed successfully. There must be something I can't see! – doplumi Dec 26 '13 at 19:07
  • 1
    and I guess, you are creating a Handler inside doInnBackground() method... – Gopal Gopi Dec 26 '13 at 19:07
  • Your second code should run properly because all the methods except the doinbackground runs on UI thread. You can perform UI actions from like onPreExecute() and onPostExecute() without any error. There may be problem with your fancyFunction method. Don't update UI from within doInBackground or fancyFunction methods. – Khawar Raza Dec 26 '13 at 19:34

1 Answers1

2

All AsyncTask methods, except for doInBackground() run on the UI Thread. Therefore, there is no reason or want to use runOnUiThread() inside of an AsyncTask and it usually causes problems (from what I've seen).

So, there is no need for it in your constructor and there also seems to be no need for a constructor in this situation at all. Also, in onPreExecute() you can just show the Dialog since it runs on the UI Thread. Same for dismissing it in onPostExecute().

So to answer your questions directly,

Is there a better way to display the dialog?

No, the way you are doing it in the second bit of code is perfectly fine and normal

Why I get the errors only in this particular AsyncTask? (the code below works well)

Not sure the exact reason without seeing all of the code but as Raghunandan said, "error usually happens when you update ui from a non ui thread" But, as stated above, there is no reason to use runOnUiThread() inside of an AsyncTask. At least no reason I know of and no reason under most circumstances.

codeMagic
  • 44,549
  • 13
  • 77
  • 93