Android : Can't create handler inside thread that has not called Looper.prepare()

6.4k views Asked by At

In my app I have a sercice class that it has this method to show progress dialog when do something :

private void openprogresdialog() {

new AsyncTask<Integer, Integer, Boolean>()
{
    ProgressDialog progressDialog;

    @Override
    protected void onPreExecute()
    {
        progressDialog = ProgressDialog.show(thisActivity, "Dialog","Loading...");
    }

    @Override
    protected Boolean doInBackground(Integer... params)
    {
        if (params == null)
        {
            return false;
        }
        try
        {
            Thread.sleep(params[0]);
        }
        catch (Exception e)
        {
            Log.e("tag", e.getMessage());
            return false;
        }

        return true;
    }

    @Override
    protected void onPostExecute(Boolean result)
    {
        progressDialog.dismiss();
        AlertDialog.Builder b = new AlertDialog.Builder(thisActivity);
        b.setTitle(android.R.string.dialog_alert_title);
        if (result)
        {
            b.setMessage("Download succeeded");
        }
        else
        {
            b.setMessage("Download failed");
        }
        b.setPositiveButton(getString(android.R.string.ok),
                new DialogInterface.OnClickListener()
                {

                    @Override
                    public void onClick(DialogInterface dlg, int arg1)
                    {
                        dlg.dismiss();
                    }
                });
        b.create().show();
    }
}.execute(2000);

new Thread()
{
    @Override
    public void run()
    {

        DialogInterface progressDialog = null;
        progressDialog.dismiss();
    }
}.start();
}

I want that while app do it's work progress dialog will show but when i run app i get this error :

Can't create handler inside thread that has not called Looper.prepare()

How can i fix it?

EDIT :

public class MyService extends Service {
    private static final String TAG = "MyService";
    Thread readthread;
    final MyService thisActivity = this;
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        final ParentActivityData data = intent.getParcelableExtra("DATA");

        readthread = new Thread(new Runnable() {
            public void run() {
                // SOME CODE TO EXECUTE //
                }
                openprogresdialog();
            }
        });

        readthread.start();

        Log.d(TAG, "onCreate");

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
    }

    @Override
    public void onDestroy() {

    }
}
5

There are 5 answers

0
Raghunandan On BEST ANSWER

You have

readthread = new Thread(new Runnable() {
            public void run() {

In the thread's run method you ahve

openprogresdialog();

In openprogresdialog you have a Asynctask and a thread.

Asynctask must be loaded on the ui thread. Check the topic Threading Rules in the link below.

http://developer.android.com/reference/android/os/AsyncTask.html

Can't create handler inside thread that has not called Looper.prepare()

You cannot update ui in a background thread. Ui should be updated on the ui thread. Your Asynctask looks fine but must be loaded on the ui thread.

Also remove the below which is useless. Will also give NullPointerException since progressDialog is not initialized and you call dismiss before initialization

new Thread()
{
    @Override
    public void run()
    {

        DialogInterface progressDialog = null;
        progressDialog.dismiss(); // even if initialized cannot update ui in a thread
    }
}.start();
2
Lovis On

Although adding Looper.prepare() is probably a valid option, I'd rather add use Activity#runOnUIThread if thats possible here. Also, why are you using a thread anyway?

It's not necessary to use a thread here.

Btw: Your code

DialogInterface progressDialog = null;
progressDialog.dismiss();

will produce a NullpointerException...

0
Sam On

You should do the UI call in the main UI thread. If you are doing in some other thread you will get this error. Since you are calling the progressDialog.dismiss from a new Thread() you are getting this error message.

2
Gooziec On

Just add Looper.prepare(); at the beggining of Your thread

new Thread()
    {
        @Override
        public void run()
        {
            Looper.prepare();
            DialogInterface progressDialog = null;
            progressDialog.dismiss();
        }
    }.start();
0
Naruto Uzumaki On
new Thread()
    {
        @Override
        public void run()
        {
            Looper.prepare();

            //Your Dialog goes here

            Looper.loop(); 
        }
    }.start();

HtH.