PDA

Ver la Versión Completa : problema con thread y toast


gohan0189
28/05/12, 21:13:16
porque no puedo poner un toast aqui (lo que esta en rojo):

Thread thread = new Thread(){
@Override
public void run()
{
while(realizado==false)
{
try{
SoapObject solicitud = new SoapObject(namespace, Metodo);

solicitud.addProperty("folioPoliza", edtxtpoliza.getText().toString());
solicitud.addProperty("inciso", edtxtinciso.getText().toString());

SoapSerializationEnvelope envoltorio = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envoltorio.dotNet = true;
envoltorio.setOutputSoapObject(solicitud);
HttpTransportSE transporte = new HttpTransportSE(url);

try {
transporte.call(accionSoap, envoltorio);
Object result = (Object)envoltorio.getResponse();
JSONString=result.toString();

DecoderConfiguration config = new DecoderConfiguration(false, AutoValueObject.class);
auto = (AutoValueObject)deserializeJsonResponse(config, JSONString);
realizado=true;

}
catch (Exception e)
{
realizado=true;
x=false;
progressDialog.dismiss();
// Toast toast = Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT);
// toast.show();
}
this.sleep(5000);
} catch (InterruptedException ex) {
Toast toast = Toast.makeText(getApplicationContext(), "Proceso terminado", Toast.LENGTH_SHORT);
toast.show();
}
}
handler.sendEmptyMessage(0);

}
};

final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {

edtxt1.setText((xxxxx).toString());
edtxt2.setText((xxxxx2).toString());
edtxt3.setText((xxxx3).toString());
edtxt4.setText((xxxx4).toString());
edtxt5.setText((xxxx5).toString());
edtxt6.setText((xxxx6).toString());
relativelayout.setVisibility(View.VISIBLE);
btobtener.setVisibility(View.GONE);
progressDialog.dismiss();

}si pongo el toast que esta en rojo me sale el siguiente error:

FATAL EXCEPTION: Thread-10
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)
at SAO.AutoHelp.Registro1$5.run(Registro1.java:182)
Activity SAO.AutoHelp.Registro1 has leaked IntentReceiver SAO.AutoHelp.Registro1$1@49dbb538 that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity SAO.AutoHelp.Registro1 has leaked IntentReceiver SAO.AutoHelp.Registro1$1@49dbb538 that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.ActivityThread$PackageInfo$ReceiverDis patcher.<init>(ActivityThread.java:940)
at android.app.ActivityThread$PackageInfo.getReceiver Dispatcher(ActivityThread.java:735)
android.app.ContextImpl.registerReceiverInternal(C ontextImpl.java:799)
android.app.ContextImpl.registerReceiver(ContextIm pl.java:786)
android.app.ContextImpl.registerReceiver(ContextIm pl.java:780)
android.content.ContextWrapper.registerReceiver(Co ntextWrapper.java:318)
SAO.AutoHelp.Registro1.onCreate(Registro1.java:76)
android.app.Instrumentation.callActivityOnCreate(I nstrumentation.java:1047)
android.app.ActivityThread.performLaunchActivity(A ctivityThread.java:2633)
android.app.ActivityThread.handleLaunchActivity(Ac tivityThread.java:2685)
android.app.ActivityThread.access$2300(ActivityThr ead.java:126)
android.app.ActivityThread$H.handleMessage(Activit yThread.java:2038)
android.os.Handler.dispatchMessage(Handler.java:99 )
android.os.Looper.loop(Looper.java:123)
android.app.ActivityThread.main(ActivityThread.jav a:4633)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:521)
com.android.internal.os.ZygoteInit$MethodAndArgsCa ller.run(ZygoteInit.java:858)
com.android.internal.os.ZygoteInit.main(ZygoteInit .java:616)
dalvik.system.NativeStart.main(Native Method)

kriogeN
28/05/12, 21:16:22
Porque los Toast tienen que ejecutarse en el hilo principal (el único hilo que tiene acceso a la pantalla), ponlo en un Handler.

gohan0189
28/05/12, 21:22:17
y si en el handler q tengo lo pongo asi :



final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(x==true){
edtxttitular.setText((auto.Poliza.Titular.NombreCo mpleto).toString());
edtxtinicio.setText((auto.Poliza.VigenciaInicio).t oString());
edtxtfinal.setText((auto.Poliza.VigenciaFin).toStr ing());
edtxtmarca.setText((auto.Marca.Descripcion).toStri ng());
edtxtmodelo.setText((auto.Modelo).toString());
edtxtversion.setText((auto.Version).toString());
relativelayout.setVisibility(View.VISIBLE);
btobtener.setVisibility(View.GONE);
progressDialog.dismiss();


}else{
Toast toast = Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT);
toast.show();

}
}


serviria????? ya que en el catch del thread hago a x como false

kriogeN
28/05/12, 21:32:00
y si en el handler q tengo lo pongo asi :



final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(x==true){
edtxttitular.setText((auto.Poliza.Titular.NombreCo mpleto).toString());
edtxtinicio.setText((auto.Poliza.VigenciaInicio).t oString());
edtxtfinal.setText((auto.Poliza.VigenciaFin).toStr ing());
edtxtmarca.setText((auto.Marca.Descripcion).toStri ng());
edtxtmodelo.setText((auto.Modelo).toString());
edtxtversion.setText((auto.Version).toString());
relativelayout.setVisibility(View.VISIBLE);
btobtener.setVisibility(View.GONE);
progressDialog.dismiss();


}else{
Toast toast = Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT);
toast.show();

}
}
serviria????? ya que en el catch del thread hago a x como false

Si, debería funcionar.

gohan0189
28/05/12, 21:50:26
me marca lo siguiente y no se xq??

java.lang.NullPointerException
SAO.AutoHelp.Registro1$6.handleMessage(Registro1.j ava:203)
android.os.Handler.dispatchMessage(Handler.java:99 )
android.os.Looper.loop(Looper.java:123)
android.app.ActivityThread.main(ActivityThread.jav a:4633)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:521)
com.android.internal.os.ZygoteInit$MethodAndArgsCa ller.run(ZygoteInit.java:858)
com.android.internal.os.ZygoteInit.main(ZygoteInit .java:616)
dalvik.system.NativeStart.main(Native Method)

gohan0189
28/05/12, 21:59:23
olvidalo Kriogen era error mio gracias por la ayuda

mocelet
28/05/12, 23:14:50
Aunque ya lo ha explicado perfectamente kriogeN, quería añadir otra alternativa:

runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT).show();
}
});


El método runOnUiThread de las Activity ejecuta lo que le pases en el hilo principal, independientemente del hilo desde donde lo llames. Te ahorra definir explicitamente el handler y andar descodificando mensajes.

Una tercera opción, no ya para los Toast sino para otras cosas, son las AsyncTask, que también ejecutan tareas en el hilo principal.

kriogeN
29/05/12, 00:14:48
Aunque ya lo ha explicado perfectamente kriogeN, quería añadir otra alternativa:

runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT).show();
}
});
El método runOnUiThread de las Activity ejecuta lo que le pases en el hilo principal, independientemente del hilo desde donde lo llames. Te ahorra definir explicitamente el handler y andar descodificando mensajes.

Una tercera opción, no ya para los Toast sino para otras cosas, son las AsyncTask, que también ejecutan tareas en el hilo principal.

Si, de hecho he dicho Handler porque he visto que ya lo tenía puesto en el código, pero yo siempre uso runOnUiThread dentro del Thread cuando quiero hacer algo en la ventana.

El AsyncTask, como ya has dicho, para este caso creo que es demasiado elaborado para tan poca cosa.

mocelet
29/05/12, 00:36:12
Sí, si lo comenté más por si alguien entraba en el hilo buscando que por resolver la duda -que ya la dejaste resuelta-.

De hecho, me parece más elegante el Handler, en las otras se corre el riesgo de llenar el código de runOnUiThread y al final no sabes ni qué estás ejecutando ni cuándo.

gohan0189
30/05/12, 01:22:33
muchas gracias , ahora otra duda como detengo un thread???

gohan0189
30/05/12, 01:28:03
bueno lo que pasa es que tengo un codigo dentro de un boton (osea al darle click) esto es lo que hace

progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Cargando datos \nespere......");
progressDialog.show();
thread.start();

y mi thread y handler asi

Thread thread = new Thread(){
@Override
public void run()
{
while(realizado==false)
{
try{
SoapObject solicitud = new SoapObject(namespace, Metodo);
///
solicitud.addProperty("dato1", edtxt1.getText().toString());
solicitud.addProperty("dato2", edtxt2.getText().toString());
///
SoapSerializationEnvelope envoltorio = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envoltorio.dotNet = true;
envoltorio.setOutputSoapObject(solicitud);
HttpTransportSE transporte = new HttpTransportSE(url);

try {
transporte.call(accionSoap, envoltorio);
Object result = (Object)envoltorio.getResponse();
JSONString=result.toString();

DecoderConfiguration config = new DecoderConfiguration(false, AutoValueObject.class);
auto = (AutoValueObject)deserializeJsonResponse(config, JSONString);
realizado=true;

}
catch (Exception e)
{
realizado=true;
x=false;

}
this.sleep(5000);
} catch (InterruptedException ex) {

}
}

handler.sendEmptyMessage(0);

}
};

final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (x==true){
//aqui solo lleno mis campos con los datos obtenidos

progressDialog.dismiss();

}else{
progressDialog.dismiss();
Toast toast = Toast.makeText(getApplicationContext(), "No se pudo comunicar con el servidor", Toast.LENGTH_SHORT);
toast.show();
realizado=false;

}

}
};

ahora si hay un error en la llamada al web service me manda el toast con el problema del servidor y me regresa y al momento de volver a dar click en el boton me saca por un error de mi app y supongo q es xq le pongo de nuevo el thread.start y basicamente nunk lo he detenido o no es asi???

mocelet
30/05/12, 18:02:07
Ya te has contestado tú solo, una instancia de Thread solo puede iniciarse una vez. Si necesitas volver a ejecutarlo tienes que crear una instancia nueva.

gohan0189
30/05/12, 18:03:28
como que una instancia nueva??

kriogeN
30/05/12, 18:18:43
como que una instancia nueva??

Siempre lo digo, pero aquí va una vez más, primero Java (con toda la teoría sobre POO incluida) y después Android.

Thead thread = new Thread() { ....... };

Thread es la clase, y thread es la instancia.

Para poder ejecutar thread.start() 2 veces tienes que volver a crear la instancia.

Pasado a limpio:

El código Thead thread = new Thread() { ....... }; tiene que estar justo antes del thread.start() en el mismo OnClick.

gohan0189
30/05/12, 18:46:41
aaaaa ok, si perdon se me fue el avion con eso de las instancias eee pjejejejeje pero ya me quedo muchas gracias a los dos