Pregunta No se puede crear el controlador dentro de la cadena que no ha llamado a Looper.prepare ()


¿Qué significa la siguiente excepción? ¿Cómo puedo arreglarlo?

Este es el código:

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);

Esta es la excepción:

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
     at android.os.Handler.<init>(Handler.java:121)
     at android.widget.Toast.<init>(Toast.java:68)
     at android.widget.Toast.makeText(Toast.java:231)

767
2017-10-06 17:18


origen


Respuestas:


Lo estás llamando desde un hilo de trabajo. Tienes que llamar Toast.makeText() (y la mayoría de las otras funciones relacionadas con la interfaz de usuario) desde el hilo principal. Podría usar un controlador, por ejemplo.

Buscar Comunicándose con el hilo de UI en la documentación. En una palabra:

// Set this up in the UI thread.

mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message message) {
        // This is where you do your work in the UI thread.
        // Your worker tells you in the message what to do.
    }
};

void workerThread() {
    // And this is how you call it from the worker thread:
    Message message = mHandler.obtainMessage(command, parameter);
    message.sendToTarget();
}

Otras opciones:

Puedes usar un AsyncTask, que funciona bien para la mayoría de las cosas que se ejecutan en segundo plano. Tiene ganchos a los que puede llamar para indicar el progreso y cuándo está listo.

También podrías usar Activity.runOnUiThread ().


541
2017-10-06 17:20



Tienes que llamar Toast.makeText(...) del hilo de la interfaz de usuario:

activity.runOnUiThread(new Runnable() {
  public void run() {
    Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show();
  }
});

Esto está copiado desde otra (duplicada) respuesta SO.


750
2018-03-22 02:11



ACTUALIZACIÓN - 2016

La mejor alternativa es usar RxAndroid (enlaces específicos para RxJava) Para el P en MVP para hacerse cargo de los datos.

Comience volviendo Observable de su método existente.

private Observable<PojoObject> getObservableItems() {
    return Observable.create(subscriber -> {

        for (PojoObject pojoObject: pojoObjects) {
            subscriber.onNext(pojoObject);
        }
        subscriber.onCompleted();
    });
}

Usa este Observable así:

getObservableItems().
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new Observer<PojoObject> () {
    @Override
    public void onCompleted() {
        // Print Toast on completion
    }

    @Override
    public void onError(Throwable e) {}

    @Override
    public void onNext(PojoObject pojoObject) {
        // Show Progress
    }
});
}

-------------------------------------------------- -------------------------------------------------- ------------------------------

Sé que llego un poco tarde, pero aquí va. Android básicamente funciona en dos tipos de subprocesos UI hilo y hilo de fondo. De acuerdo con la documentación de Android -

No acceda al kit de herramientas de la interfaz de usuario de Android desde fuera del subproceso de la interfaz de usuario para solucionar este problema. Android ofrece varias formas de acceder al subproceso de la interfaz de usuario desde otros subprocesos. Aquí hay una lista de métodos que pueden ayudar:

Activity.runOnUiThread(Runnable)  
View.post(Runnable)  
View.postDelayed(Runnable, long)

Ahora hay varios métodos para resolver este problema.

Lo explicaré por muestra de código:

runOnUiThread

new Thread()
{
    public void run()
    {
        myactivity.this.runOnUiThread(new Runnable()
        {
            public void run()
            {
                //Do your UI operations like dialog opening or Toast here
            }
        });
    }
}.start();

LOOPER

Clase utilizada para ejecutar un bucle de mensaje para un hilo. Los hilos por defecto hacen   no tener un bucle de mensaje asociado a ellos; para crear uno, llame   prepare () en el hilo que ejecutará el ciclo, y luego loop () para   hacer que procesen mensajes hasta que se detenga el ciclo.

class LooperThread extends Thread {
    public Handler mHandler;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();
    }
}

AsyncTask

AsyncTask le permite realizar un trabajo asincrónico en su usuario   interfaz. Realiza las operaciones de bloqueo en un hilo de trabajo y   luego publica los resultados en el hilo de UI, sin necesidad de que   maneja los hilos y / o manejadores usted mismo.

public void onClick(View v) {
    new CustomTask().execute((Void[])null);
}


private class CustomTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... param) {
        //Do some work
        return null;
    }

    protected void onPostExecute(Void param) {
        //Print Toast or open dialog
    }
}

Entrenador de animales

Un controlador le permite enviar y procesar mensajes y objetos ejecutables   asociado con MessageQueue de un hilo.

Message msg = new Message();


new Thread()
{
    public void run()
    {
        msg.arg1=1;
        handler.sendMessage(msg);
    }
}.start();



Handler handler = new Handler(new Handler.Callback() {

    @Override
    public boolean handleMessage(Message msg) {
        if(msg.arg1==1)
        {
            //Print Toast or open dialog        
        }
        return false;
    }
});

412
2018-06-02 19:32



Intente esto, cuando vea runtimeException debido a que Looper no está preparado antes del controlador.

Handler handler = new Handler(Looper.getMainLooper()); 

handler.postDelayed(new Runnable() {
  @override
  void run() {
  // Run your task here
  }
}, 1000 );

65
2018-06-13 07:26



Me encontré con el mismo problema, y ​​así es como lo arreglé:

private final class UIHandler extends Handler
{
    public static final int DISPLAY_UI_TOAST = 0;
    public static final int DISPLAY_UI_DIALOG = 1;

    public UIHandler(Looper looper)
    {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg)
    {
        switch(msg.what)
        {
        case UIHandler.DISPLAY_UI_TOAST:
        {
            Context context = getApplicationContext();
            Toast t = Toast.makeText(context, (String)msg.obj, Toast.LENGTH_LONG);
            t.show();
        }
        case UIHandler.DISPLAY_UI_DIALOG:
            //TBD
        default:
            break;
        }
    }
}

protected void handleUIRequest(String message)
{
    Message msg = uiHandler.obtainMessage(UIHandler.DISPLAY_UI_TOAST);
    msg.obj = message;
    uiHandler.sendMessage(msg);
}

Para crear UIHandler, deberá realizar lo siguiente:

    HandlerThread uiThread = new HandlerThread("UIHandler");
    uiThread.start();
    uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());

Espero que esto ayude.


39
2017-11-30 19:35



Motivo de un error:

Los subprocesos de trabajo están diseñados para realizar tareas en segundo plano y no se puede mostrar nada en la interfaz de usuario dentro de un subproceso de trabajo a menos que llame a un método como runOnUiThread. Si intenta mostrar algo en el hilo de UI sin llamar a runOnUiThread, habrá un java.lang.RuntimeException.

Entonces, si estás en un activity pero llamando Toast.makeText() del hilo de trabajo, haz esto:

runOnUiThread(new Runnable() 
{
   public void run() 
   {
      Toast toast = Toast.makeText(getApplicationContext(), "Something", Toast.LENGTH_SHORT).show();    
   }
}); 

El código anterior asegura que está mostrando el mensaje Toast en una UI thread ya que lo estás llamando adentro runOnUiThread método. Así que no más java.lang.RuntimeException.


32
2018-05-16 07:40



Toast.makeText() debe llamarse desde el hilo Principal / IU. Looper.getMainLooper() te ayuda a lograrlo:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);
    }
});

Una ventaja de este método es que también puede usarlo en clases que no son de Actividad (o sin contexto).


25
2018-01-24 00:27



Estaba obteniendo este error hasta que hice lo siguiente.

public void somethingHappened(final Context context)
{
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(
        new Runnable()
        {
            @Override
            public void run()
            {
                Toast.makeText(context, "Something happened.", Toast.LENGTH_SHORT).show();
            }
        }
    );
}

Y lo convirtió en una clase singleton:

public enum Toaster {
    INSTANCE;

    private final Handler handler = new Handler(Looper.getMainLooper());

    public void postMessage(final String message) {
        handler.post(
            new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(ApplicationHolder.INSTANCE.getCustomApplication(), message, Toast.LENGTH_SHORT)
                        .show();
                }
            }
        );
    }

}

21
2017-11-20 13:09



eso fue lo que hice.

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Toast(...);
    }
});

Los componentes visuales están "bloqueados" a los cambios de los subprocesos externos. Por lo tanto, dado que el brindis muestra cosas en la pantalla principal administradas por el hilo principal, debe ejecutar este código en ese hilo. Espero que ayude:)


17
2018-03-16 16:13