¿Cómo mostrar un Toast en Android AsyncTask?
android-asynctask (7)
Estoy intentando mostrar Toast en mi clase initial_background extendida con AsyncTask<URL, Integer, Long>
. Estoy recibiendo este error en logcat.
public class InitialBackgroundTask extends AsyncTask<URL, Integer, Long> {
@Override
protected Long doInBackground(URL... params) {
// TODO Auto-generated method stub
show a = new show();
a.loop();
return null;
}
public class show {
void loop()
{
for(int i=0; i<10; i++)
{
Toast.makeText(MainActivity.me, "test", Toast.LENGTH_LONG).show();
}
}
}
Esta es la excepción:
05-30 12:08:12.641: E/AndroidRuntime(30840): FATAL EXCEPTION: AsyncTask #1
05-30 12:08:12.641: E/AndroidRuntime(30840): java.lang.RuntimeException: An error occured while executing doInBackground()
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$3.done(AsyncTask.java:278)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.lang.Thread.run(Thread.java:856)
05-30 12:08:12.641: E/AndroidRuntime(30840): Caused by: java.lang.RuntimeException: Can''t create handler inside thread that has not called Looper.prepare()
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.Handler.<init>(Handler.java:121)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast$TN.<init>(Toast.java:317)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast.<init>(Toast.java:91)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.widget.Toast.makeText(Toast.java:233)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.show.loop(show.java:11)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.java:13)
05-30 12:08:12.641: E/AndroidRuntime(30840): at com.example.toast.InitialBackgroundTask.doInBackground(InitialBackgroundTask.java:1)
05-30 12:08:12.641: E/AndroidRuntime(30840): at android.os.AsyncTask$2.call(AsyncTask.java:264)
05-30 12:08:12.641: E/AndroidRuntime(30840): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-30 12:08:12.641: E/AndroidRuntime(30840): ... 5 more
El código anterior está mostrando toda la historia. En realidad, quiero mostrar tostadas en el método doInBackground
Crea un objeto controlador y ejecuta todos tus mensajes de Toast usando eso.
@Override
protected Void doInBackground(Void... params) {
Handler handler = new Handler(context.getMainLooper());
handler.post( new Runnable(){
public void run(){
Toast.makeText(context, "Created a server socket",Toast.LENGTH_LONG).show();
}
});
}
Está intentando mostrar un brindis en un subproceso que no es de la interfaz de usuario, por eso aparece este error.
Si desea mostrar las tostadas en el método doInBackground, debe escribir su lógica Toast dentro del hilo de la interfaz de usuario
Eche un vistazo en el siguiente enlace de respuesta https://.com/a/11797945/582571
Pero no es recomendable tener una manipulación de la interfaz de usuario en un subproceso no ui
Esta es otra forma que no se menciona aquí como sigue:
Paso 1: Definir Handler como global
Handler handler;
Paso 2: Inicialice el controlador en el método doInBackground () de la siguiente manera:
@Override
protected Void doInBackground(Void... params) {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//your code
}
}
};
}
Paso 3: Y ahora puedes llamar a ese controlador por cualquier parte del código llamando
if(handler != null){
handler.sendEmptyMessage(1);
}
Lo que más puede hacer es enviar datos a través del controlador de la siguiente manera:
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putInt("KEY", value);
message.setData(bundle);
handler.sendMessage(message);
Y maneje los datos en su controlador como se muestra abajo
handler = new Handler(){
@Override
public void handleMessage(Message message) {
Bundle bundle = message.getData();
Integer value = bundle.getInt("KEY");
}
};
No puede actualizar la interfaz de usuario en el hilo de fondo. doInBackground()
se invoca en el subproceso de fondo. Debe actualizar la interfaz de usuario en el hilo de la interfaz de usuario.
runOnUiThread(new Runnable(){
@Override
public void run(){
//update ui here
// display toast here
}
});
onPreExecute()
, onPostExecute(Result)
, se invocan en el subproceso de la interfaz de usuario. Así que puedes mostrar tostadas aquí.
onProgressUpdate(Progress...)
, invocado en el hilo de la IU después de una llamada a publishProgress(Progress...)
puede usarse para animar una barra de progreso o mostrar registros en un campo de texto.
El resultado del doInBackground()
de doInBackground()
es un parámetro para onPostExecute(Result)
por lo tanto, devuelva el resultado en doinBackground()
y muestre su brindis en onPostExecute(Result)
También puede usar un controlador como lo sugiere @Stine Pike
Para mayor claridad, consulte el siguiente enlace bajo el tema: Los 4 pasos .
http://developer.android.com/reference/android/os/AsyncTask.html
No puede mostrar Toast en un hilo sin interfaz de usuario (es decir, hacer en segundo plano). Puede probar el concepto de bandera.
public class HttpRequest extends AsyncTask<String[], Void, String> {
boolean flag=false;
....
...
....
@Override
protected String doInBackground(String[]... params) {
//set flag as true when you need to trigger the Toast
try{
//Some Network Calls
} catch (HttpHostConnectException e) {
flag=true;
//Triggered Flas when i got Exceptions
}
}
@Override
protected void onPostExecute(String result) {
if(flag){
Toast.makeText(activity, "HttpHostConnectException Occured ", Toast.LENGTH_SHORT).show();
}
}
Codificación feliz .. !!! ingresa el código aquí
muestre su Toast en onPostExecute o onPreExecute. doInBackGround se ejecuta en un subproceso separado, pero los otros dos métodos se ejecutan en el subproceso de la interfaz de usuario.
Pero si es necesario mostrar el brindis en doInBackGround, entonces puede usar Handler.post o runonUiThread para realizar la presentación de brindis.
podemos hacer esto pasando una interfaz a la clase AsyncTask y hacer una devolución de llamada en el método onPostExecute .
public interface IResult {
void onSuccess(String result);
void onError(String error);
}
public static class AsyncTaskClass extends AsyncTask<String, String, Boolean> {
IResult iResult;
AsyncTaskClass(IResult iResult){
this.iResult = iResult;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Boolean doInBackground(String... params) {
boolean result;
try {
//doing BackGround Operation Here
result = true;
} catch (Exception e) {
Log.e(TAG,"Error: " + e.getMessage());
result = false;
}
return result;
}
@Override
protected void onPostExecute(Boolean success) {
super.onPostExecute(success);
Log.w(TAG, "On Post Execute: " + success);
if(success)
iResult.onSuccess("AsyncTask done successfully.");
else
iResult.onSuccess("Sorry! something went wrong.");
}
}
IResult iResult = new IResult() {
@Override
public void onSuccess(String result) {
Toast.makeText(PostActivity.this, result, Toast.LENGTH_LONG).show();
}
@Override
public void onError(String error) {
Toast.makeText(PostActivity.this, error, Toast.LENGTH_LONG).show();
}
};
String param1 = "some value 1";
String param2 = "some value 2";
new AsyncTaskClass(iResult).execute(param1, param2);`