Android: невозможно создать обработчик внутри потока, который не вызвал Looper.prepare()

В моем приложении у меня есть класс обслуживания, в котором есть этот метод для отображения диалогового окна прогресса, когда что-то делается:

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();
}

Я хочу, чтобы пока приложение выполняло свою работу, отображалось диалоговое окно, но когда я запускаю приложение, я получаю эту ошибку:

Невозможно создать обработчик внутри потока, который не вызывал Looper.prepare()

Как я могу это исправить?

ИЗМЕНИТЬ:

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() {

    }
}

person Elham Gdz    schedule 17.12.2013    source источник
comment
progressDialog.dismiss(); это в теме. удалить саму ветку   -  person Raghunandan    schedule 17.12.2013


Ответы (5)


У тебя есть

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

В методе запуска потока у вас есть

openprogresdialog();

В openprogresdialog у вас есть асинтаск и поток.

Асинтаск должен быть загружен в поток пользовательского интерфейса. Ознакомьтесь с разделом «Правила создания потоков» по ​​ссылке ниже.

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

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

Вы не можете обновить пользовательский интерфейс в фоновом потоке. Пользовательский интерфейс должен быть обновлен в потоке пользовательского интерфейса. Ваша асинтаска выглядит нормально, но должна быть загружена в поток пользовательского интерфейса.

Также удалите ниже, что бесполезно. Также даст NullPointerException, так как progressDialog не инициализирован и вы вызываете dismiss перед инициализацией

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

        DialogInterface progressDialog = null;
        progressDialog.dismiss(); // even if initialized cannot update ui in a thread
    }
}.start();
person Raghunandan    schedule 17.12.2013

Хотя добавление Looper.prepare(), вероятно, является допустимым вариантом, я бы предпочел добавить использование Activity#runOnUIThread, если это возможно здесь. Кроме того, почему вы все равно используете поток?

Здесь нет необходимости использовать тему.

Кстати: ваш код

DialogInterface progressDialog = null;
progressDialog.dismiss();

создаст исключение NullpointerException...

person Lovis    schedule 17.12.2013
comment
так что я делаю вместо этого? - person Elham Gdz; 17.12.2013
comment
@ElhamGdz после вашего редактирования мой ответ теперь недействителен. - person Lovis; 17.12.2013

Просто добавьте Looper.prepare(); в начало темы

new Thread()
    {
        @Override
        public void run()
        {
            Looper.prepare();
            DialogInterface progressDialog = null;
            progressDialog.dismiss();
        }
    }.start();
person Gooziec    schedule 17.12.2013
comment
@ElhamGdz удалите нить, которая ничего не делает. асинтаск в порядке. Также вы не можете обновить пользовательский интерфейс из потока. Это должно быть сделано в потоке пользовательского интерфейса. DialogInterface progressDialog = null; progressDialog.dismiss(); даст NPE, потому что progressDialog равно null - person Raghunandan; 17.12.2013
comment
Проблема в том, что вы вызываете асинхронную задачу в другой задаче. Попробуйте добавить Looper.prepare() readthread = new Thread(new Runnable() { public void run() { Looper.prepare(); ...}; - person Gooziec; 17.12.2013

Вы должны сделать вызов пользовательского интерфейса в основном потоке пользовательского интерфейса. Если вы делаете это в каком-то другом потоке, вы получите эту ошибку. Поскольку вы вызываете progressDialog.dismiss из нового Thread(), вы получаете это сообщение об ошибке.

person Sam    schedule 17.12.2013

new Thread()
    {
        @Override
        public void run()
        {
            Looper.prepare();

            //Your Dialog goes here

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

HtH.

person Naruto Uzumaki    schedule 15.04.2015