Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare () - PullRequest
79 голосов
/ 16 февраля 2011

У меня есть активность, и в этом у меня есть класс.

text=new Dynamictext(...);
text.setText("txt");

в моем DynamicText Java у меня есть этот код:

public void setText(String text) {
    this.text=text;
    new asyncCreateText().execute();
    //this.createText(text);
}

//private Handler handler = new Handler();

private class asyncCreateText extends AsyncTask<Void, Void, Void> 
{
    @Override
    protected Void doInBackground(Void... unused) {
        return null;
    }

    @Override
    protected void onPostExecute(Void unused) {

    }
}

Я получаю:

ОШИБКА / AndroidRuntime (5176): Причина: java.lang.RuntimeException: Невозможно создать обработчик внутри потока, который не вызвал Looper.prepare ()

Как мне справиться с этой ошибкой?

ERROR/AndroidRuntime(5370): java.lang.ExceptionInInitializerError
ERROR/AndroidRuntime(5370):     at com.l.start.DynamicText.setText(DynamicText.java:125)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.initfonts(OpenGLRenderer.java:168)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.init(OpenGLRenderer.java:119)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.onSurfaceChanged(OpenGLRenderer.java:90)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1120)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)

ERROR/AndroidRuntime(5370): Caused by: java.lang.RuntimeException: 
    Can't create handler inside thread that has not called Looper.prepare()
ERROR/AndroidRuntime(5370):     at android.os.Handler.<init>(Handler.java:121)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
ERROR/AndroidRuntime(5370):     ... 6 more

Ответы [ 6 ]

145 голосов
/ 16 февраля 2011

Ошибка не требует пояснений ... doInBackground() работает в фоновом потоке, который, поскольку он не предназначен для зацикливания, не подключен к Looper.

Скорее всего, вы не 'вообще не нужно напрямую создавать экземпляр обработчика ... все данные, которые возвращает ваша реализация doInBackground(), будут переданы onPostExecute(), который выполняется в потоке пользовательского интерфейса.Появляется в вопросе:

Похоже, вы пытаетесь запустить AsyncTask из потока рендеринга GL ... не делайте этого, потому что они тоже никогда не будут Looper.loop().AsyncTasks действительно предназначены для запуска только из потока пользовательского интерфейса.

Наименее разрушительным решением, вероятно, будет вызов Activity.runOnUiThread() с Runnable, который запускает ваш AsyncTask.

31 голосов
/ 05 апреля 2012

Все ответы выше верны, но я думаю, что это самый простой пример:

public class ExampleActivity extends Activity {
    private Handler handler;
    private ProgressBar progress;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        progress = (ProgressBar) findViewById(R.id.progressBar1);
        handler = new Handler();
    }

    public void clickAButton(View view) {
        // Do something that takes a while
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                handler.post(new Runnable() { // This thread runs in the UI
                    @Override
                    public void run() {
                        progress.setProgress("anything"); // Update the UI
                    }
                });
            }
        };
        new Thread(runnable).start();
    }
}

Это обновляет индикатор выполнения в потоке пользовательского интерфейса из совершенно другого потока, передаваемого через метод post () обработчика, объявленного в действии.

Надеюсь, это поможет!

20 голосов
/ 22 декабря 2014

Таким способом вы создаете обработчик в фоновом потоке

private void createHandler() {
        Thread thread = new Thread() {
          public void run() {
               Looper.prepare();

               final Handler handler = new Handler();
               handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                       // Do Work
                        handler.removeCallbacks(this);
                        Looper.myLooper().quit();
                   }
                }, 2000);

                Looper.loop();
            }
        };
        thread.start();
    }
11 голосов
/ 01 августа 2011

Activity.runOnUiThread() у меня не работает. Я обошел эту проблему, создав обычную тему следующим образом:

public class PullTasksThread extends Thread {
   public void run () {
      Log.d(Prefs.TAG, "Thread run...");
   }
}

и вызов его из GL обновите следующим образом:

new PullTasksThread().start();
4 голосов
/ 08 июля 2013

Попробуйте запустить свою асинхронную задачу из потока пользовательского интерфейса. Я столкнулся с этой проблемой, когда я не делал то же самое!

2 голосов
/ 13 февраля 2017

Попробуйте это

    Handler mHandler = new Handler(Looper.getMainLooper());
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
 //your code here that talks with the UI level widgets/ try to access the UI 
//elements from this block because this piece of snippet will run in the UI/MainThread.                                     
                            }
                        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...