No se puede crear el controlador dentro de hilo que no ha llamado Looper.prepare ()
¿Qué significa la siguiente excepción? ¿Cómo puedo arreglarlo?
Este es el código:
- Configuración de TextView visible desde otro hilo o BeginInvoke en Android
- DoInBackground llama a AsyncTask entonces duerme bloques UI Thread
- Diferencia entre Handler.post (Runnable r) y Activity.runOnUiThread (Runnable r)
- IU de Android: ¿cuándo puedo modificar directamente una vista?
- ¿Por qué se utiliza un único modelo de subproceso para actualizar la interfaz de usuario como subproceso principal?
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)
- Android: ¿Posible que el hilo de fondo bloquee hasta que el hilo de UI finalice la operación?
- ¿Por qué sólo el subproceso de interfaz de usuario en Android puede actualizar la interfaz de usuario?
- Animación de una vista mientras que ListView no está funcionando
- ¿Es una buena práctica crear AsyncTask anónima para paralelo pequeño proceso de congelación conocido?
- No error "Sólo el subproceso original que creó una jerarquía de vista puede tocar sus vistas" cuando la vista se actualiza sin demora
- ¿Qué sucede con un AsyncTask cuando la actividad de lanzamiento se detiene / destruye mientras todavía se está ejecutando?
- Admob: Cómo cargar AdRequest fuera de UI Thread?
- Cómo utilizar runOnUiThread
Lo estás llamando desde un hilo de trabajo. Necesita llamar a Toast.makeText()
(y la mayoría de las demás funciones que se ocupan de la interfaz de usuario) desde el subproceso principal. Por ejemplo, podrías usar un manejador.
Buscar Comunicación con el subproceso de interfaz de usuario 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:
Usted podría utilizar un AsyncTask , que funciona bien para la mayoría de las cosas que se ejecutan en el fondo. Tiene ganchos que puede llamar para indicar el progreso, y cuando se hace.
También puede utilizar Activity.runOnUiThread () .
Necesita llamar a Toast.makeText(...)
desde el subproceso de la interfaz de usuario:
activity.runOnUiThread(new Runnable() { public void run() { Toast.makeText(activity, "Hello", Toast.LENGTH_SHORT).show(); } });
Esto es copia-pegado de otro (duplicado) SO respuesta .
ACTUALIZACIÓN – 2016
La mejor alternativa es usar RxAndroid
(enlaces específicos para RxJava
) para que el P
en MVP
haga cargo de los datos.
Comience por devolver Observable
de su método existente.
private Observable<PojoObject> getObservableItems() { return Observable.create(subscriber -> { for (PojoObject pojoObject: pojoObjects) { subscriber.onNext(pojoObject); } subscriber.onCompleted(); }); }
Utilice este Observable como este –
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 estoy un poco tarde, pero aquí va. Android básicamente funciona en dos tipos de hilos, a saber, el hilo de la interfaz de usuario y el hilo de fondo . De acuerdo con la documentación de Android –
No tiene acceso al kit de herramientas de la interfaz de usuario de Android desde fuera del hilo de la interfaz de usuario para solucionar este problema, Android ofrece varias formas de acceder al subproceso de interfaz de usuario de 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 ejemplo 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 subproceso. Los hilos por defecto no tienen un bucle de mensaje asociado con ellos; Para crear uno, llame prepare () en el subproceso que va a ejecutar el bucle, y luego loop () para que los mensajes de proceso hasta que el bucle se detiene.
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 trabajo asincrónico en su interfaz de usuario. Realiza las operaciones de bloqueo en un subproceso de trabajo y luego publica los resultados en el subproceso de interfaz de usuario, sin necesidad de que usted mismo maneje subprocesos y / o controladores.
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 asociados con MessageQueue de un subproceso.
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; } });
Pruebe esto, cuando vea runtimeException debido a Looper no preparado antes del controlador.
Handler handler = new Handler(Looper.getMainLooper()); handler.postDelayed(new Runnable() { @override void run() { // Run your task here } }, 1000 );
Me encontré con el mismo problema, y aquí es cómo 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 el UIHandler, necesitará realizar lo siguiente:
HandlerThread uiThread = new HandlerThread("UIHandler"); uiThread.start(); uiHandler = new UIHandler((HandlerThread) uiThread.getLooper());
Espero que esto ayude.
Motivo del error:
Los hilos de trabajo están destinados a realizar tareas de fondo y no se puede mostrar nada en la interfaz de usuario dentro de un subproceso de trabajo a menos que se llame al método runOnUiThread . Si intenta mostrar algo en el subproceso de UI sin llamar a runOnUiThread, habrá un java.lang.RuntimeException
.
Por lo tanto, si está en una activity
pero llama a Toast.makeText()
desde el subproceso de trabajo, haga lo siguiente:
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 un UI thread
ya que lo está llamando dentro del método runOnUiThread
. Así que no más java.lang.RuntimeException
.
Estaba recibiendo 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 convirtió esto 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(); } } ); } }
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 hilos externos. Por lo tanto, dado que el brindis muestra cosas en la pantalla principal que es administrada por el hilo principal, es necesario ejecutar este código en ese hilo. Espero que ayude:)
Una ventaja de este método es que se puede utilizar en clases que no sean de actividad también:
new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); } });
La respuesta de ChicoBird funcionó para mí. El único cambio que hice fue en la creación del UIHandler donde tenía que hacer
HandlerThread uiThread = new HandlerThread("UIHandler");
Eclipse se negó a aceptar cualquier otra cosa. Tiene sentido supongo.
También el uiHandler
es claramente una clase global definida en alguna parte. Sigo sin pretender entender cómo Android está haciendo esto y lo que está pasando, pero me alegro de que funcione. Ahora voy a proceder a estudiarlo y ver si puedo entender lo que está haciendo Android y por qué uno tiene que pasar por todos estos aros y bucles. Gracias por la ayuda ChicoBird.
Esto es porque Toast.makeText () está llamando desde un subproceso de trabajo. Debe ser llamada desde el hilo principal de la interfaz de usuario como este
runOnUiThread(new Runnable() { public void run() { Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT); } });
Estaba funcionando en el mismo problema cuando mis devoluciones de llamada intentarían demostrar un diálogo.
Lo solucioné con métodos dedicados en la actividad – en el nivel de miembro de instancia de Activity – que utilizan runOnUiThread(..)
public void showAuthProgressDialog() { runOnUiThread(new Runnable() { @Override public void run() { mAuthProgressDialog = DialogUtil.getVisibleProgressDialog(SignInActivity.this, "Loading ..."); } }); } public void dismissAuthProgressDialog() { runOnUiThread(new Runnable() { @Override public void run() { if (mAuthProgressDialog == null || ! mAuthProgressDialog.isShowing()) { return; } mAuthProgressDialog.dismiss(); } }); }
Para Rxjava y RxAndroid Usuario:
public static void shortToast(String msg) { Observable.just(msg) .observeOn(AndroidSchedulers.mainThread()) .subscribe(message -> { Toast.makeText(App.getInstance(), message, Toast.LENGTH_SHORT).show(); }); }
Toast, AlertDialogs necesita ejecutarse en el hilo de interfaz de usuario, puede utilizar Asynctask para usarlos correctamente en android development.but algunos casos tenemos que personalizar los tiempos de espera, por lo que usamos Threads , pero en los hilos no podemos usar Toast, Alertdialogs como we using En AsyncTask.So necesitamos manejador separado para popup los.
public void onSigned() { Thread thread = new Thread(){ @Override public void run() { try{ sleep(3000); Message message = new Message(); message.what = 2; handler.sendMessage(message); } catch (Exception e){ e.printStackTrace(); } } }; thread.start(); }
En el ejemplo de arriba quiero dormir mi hilo en 3sec y después quiero mostrar un mensaje de Toast, para eso en su mainthread implementar manejador.
handler = new Handler() { public void handleMessage(Message msg) { switch(msg.what){ case 1: Toast.makeText(getActivity(),"cool",Toast.LENGTH_SHORT).show(); break; } super.handleMessage(msg); } };
Utilicé el caso del interruptor aquí, porque si usted necesita mostrar el mensaje diferente de la misma manera, usted puede utilizar la caja del interruptor dentro de la clase del manejo … espere que esto le ayudará
Para mostrar un diálogo o una tostadora en un subproceso, la forma más concisa es utilizar el objeto Activity.
Por ejemplo:
new Thread(new Runnable() { @Override public void run() { myActivity.runOnUiThread(new Runnable() { public void run() { myActivity.this.processingWaitDialog = new ProgressDialog(myActivity.this.getContext()); myActivity.this.processingWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); myActivity.this.processingWaitDialog.setMessage("abc"); myActivity.this.processingWaitDialog.setIndeterminate(true); myActivity.this.processingWaitDialog.show(); } }); expenseClassify.serverPost( new AsyncOperationCallback() { public void operationCompleted(Object sender) { myActivity.runOnUiThread(new Runnable() { public void run() { if (myActivity.this.processingWaitDialog != null && myActivity.this.processingWaitDialog.isShowing()) { myActivity.this.processingWaitDialog.dismiss(); myActivity.this.processingWaitDialog = null; } } }); // .runOnUiThread(new Runnable() ...
- Android – necesito algunas aclaraciones de fragmentos vs actividades y vistas
- Cómo convertir un dibujable a un mapa de bits?