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

Я пытаюсь запустить сетевой процесс в фоновом режиме моего приложения, чтобы отправить электронное письмо. Поскольку это сетевая задача, ее нужно запускать в отдельном потоке в фоновом режиме. Однако я не могу заставить поток выполняться должным образом. Чтобы начать новый поток, я просто создаю его и запускаю с помощью Thread.start(),

    new Thread(){


        public void run(){
                            Mail mail = new Mail();
            mail.setFrom("[email protected]");
            mail.setTo("[email protected]");
            mail.setSubject("Hello");
            mail.setMessage("World");

            try
            {
                if (mail.send())
                {
                    Toast.makeText(getActivity(),
                            "Email Sent Successfully", Toast.LENGTH_LONG)
                            .show();
                }

                else
                    Toast.makeText(getActivity(),
                            "Email Not Sent", Toast.LENGTH_LONG).show();

            }
            catch (Exception e)
            {
                Log.i("Debug","Could not send email - " + e);
                Log.i("Debug",e.getStackTrace().toString());
            }


        }
    }.start();

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

Я попробовал еще несколько вещей, пытаясь передать Looper.getMainLooper() потоку через обработчик с Runnable, но это дает мне ту же ошибку. Я также пытался использовать AsyncTask, но кажется, что, поскольку это не операция пользовательского интерфейса, использование AsyncTask неверно (плюс, это также дает мне ту же ошибку).

Вот мой стек

 03-01 16:14:43.305: I/GreenBook(4454): java.lang.RuntimeException: Can't create handler inside     thread that has not called Looper.prepare()
03-01 16:14:43.305: I/GreenBook(4454):  at android.os.Handler.<init>(Handler.java:121)
03-01 16:14:43.305: I/GreenBook(4454):  at android.widget.Toast$TN.<init>(Toast.java:361)
03-01 16:14:43.305: I/GreenBook(4454):  at android.widget.Toast.<init>(Toast.java:97)
03-01 16:14:43.305: I/GreenBook(4454):  at android.widget.Toast.makeText(Toast.java:254)
03-01 16:14:43.305: I/GreenBook(4454):  at     com.stacksmashers.greenbook.RegisterActivity$10.run(RegisterActivity.java:688)

person sparkonhdfs    schedule 01.03.2014    source источник
comment
Пожалуйста, опубликуйте трассировку стека.   -  person CommonsWare    schedule 02.03.2014
comment
Это в моем вопросе сейчас.   -  person sparkonhdfs    schedule 02.03.2014
comment
Вы должны предоставить свою полную трассировку стека.   -  person nKn    schedule 02.03.2014
comment
Это полная трассировка стека. Только поток поймал исключение, поэтому он не привел к сбою всего приложения, поэтому приложение продолжало работать даже после сбоя потока.   -  person sparkonhdfs    schedule 02.03.2014
comment
Какая строка 688 вашего файла RegisterActivity.java?   -  person nKn    schedule 02.03.2014
comment
Это строка if (mail.send()), потому что она ожидает возврата метода Mail send после отправки почты. (Я знаю, что почтовые классы/методы работают, потому что я тестировал их раньше)   -  person sparkonhdfs    schedule 02.03.2014
comment
Ну, вот где виновник. Это, вероятно, создает Handler, а ваш Thread не имеет оператора Looper.prepare().   -  person nKn    schedule 02.03.2014


Ответы (1)


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

Это потому, что вы пытаетесь показать Toast.

Я также пытался использовать AsyncTask, но кажется, что, поскольку это не операция пользовательского интерфейса, использование AsyncTask неверно.

Большинство разработчиков считают Toast частью пользовательского интерфейса.

плюс, это также дает мне ту же ошибку

Возможно, вы пытаетесь показать Toast из doInBackground(). Покажите свой Toast в onPostExecute() (или onProgressUpdate(), если вы решите позвонить publishProgress()).

person CommonsWare    schedule 01.03.2014
comment
Спасибо! Это решило проблему! Я не осознавал, что работаю с пользовательским интерфейсом в своем методе. Я только что вызвал Toast в методе OnProgressUpdate как часть задачи Async. - person sparkonhdfs; 02.03.2014
comment
проверьте эту библиотеку compile 'com.shamanland:xdroid-toaster:0.0.5', она не требует переменных runOnUiThread() или Context, вся рутина исчезла! просто вызовите Toaster.toast(R.string.my_msg); вот пример: github.com/shamanland/xdroid-toaster-example - person Oleksii K.; 17.07.2014