|
||
|
![]() |
![]() |
Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android |
![]() |
|
Herramientas |
#1
|
||||
|
||||
Hilos AsyncTask
Hola, estoy en pleno desarrollo de mi proyecto final de carrera y tengo un problema con los hilos de Android, resulta que necesito que cuando le de a un botón finalice un hilo para realizar otras operaciones, lo que con un Thread normal en java se haria con el metodo join().
Para que entendais un poco mejor mi problema os paso el siguiente codigo: public class PruebaActivity extends Activity { private Button button1; private Button button2; private Button button3; private ThreadPers thread; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); thread = new ThreadPers(); button1 = (Button) findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener(){ public void onClick(View v) { thread = new ThreadPers(); thread.execute(); } }); button2 = (Button) findViewById(R.id.button2); button2.setOnClickListener(new OnClickListener(){ public void onClick(View v) { thread.finish(); if(thread.getStatus() == AsyncTask.Status.FINISHED) System.out.println("FINISHED"); if(thread.getStatus() == AsyncTask.Status.RUNNING) System.out.println("RUNNING"); if(thread.getStatus() == AsyncTask.Status.PENDING) System.out.println("PENDING"); } }); button3 = (Button) findViewById(R.id.button3); button3.setOnClickListener(new OnClickListener(){ public void onClick(View v) { if(thread.getStatus() == AsyncTask.Status.FINISHED) System.out.println("FINISHED"); if(thread.getStatus() == AsyncTask.Status.RUNNING) System.out.println("RUNNING"); if(thread.getStatus() == AsyncTask.Status.PENDING) System.out.println("PENDING"); } }); } } Por supuesto ThreadPers hereda de AsyncTask. Para que me entendais una vez pulso el botón1, comienza el thread, y cuando pulso el botón2 activo un flag para que acabe pero imprime RUNNING, si después pulso el botón3 ya pone FINISHED. En mi caso lo que necesito es que en el mismo botón2 despues de llamar al método thread.finish() espere a que acabe por completo (lo que se haria con un join() en un thread común) y siga ejecutando otras instrucciones con garantias de que el thread ha acabado por completo. Saludos y gracias de antemano |
|
#2
|
||||
|
||||
En tu caso lo más recomendable es que si quieres hacer algo que se ejecute al terminar el AsyncTask lo hagas en el onPostExecute del AsyncTask, que para eso está.
Los AsyncTask están pensados para tener una parte de su ejecución corriendo sobre el hilo principal, que de hecho es lo que hace el onProgressUpdate, así que eso de poner un join en el hilo principal para esperar a alguien que puede ser que ejecute algo en el hilo principal... malo malo. Si quieres hacer algo a más bajo nivel tendrás que recurrir a los thread, y si quieres que el thread haga una determinada cosa en el hilo principal meterlo en un Handler, pero te repito lo mismo, no se como se comportará el sistema si le haces un join y de pronto quiere hacer algo en un Handler, yo pienso que se va a colgar. |
#3
|
||||
|
||||
Si quieres finalizar un hilo usa una variable de control en plan running=true y que sea el propio hilo el que deje de hacer cosas y acabe naturalmente al comprobar que es false.
Ni joins ni semáforos ni stop ni nada similar. Dan quebraderos de cabeza si no son perfectos. P.D. eso me pasa por leer rápido, si quieres que el hilo avise de que ha terminado puedes jugar con los handlers y con el postRunnable, que viene a ser lo que hace el asynctask ![]()
__________________
El mejor Cuatro en Raya de Android (Hilo en HTCMania, Play Store) ¡Un millón de descargas!
Última edición por mocelet Día 01/08/12 a las 18:41:51. |
#4
|
||||
|
||||
Hola,
Tienes que cambiar el chip en esto de los hilos. Usa los métodos del AsyncTask. Están muy bien, es mucho mejor que los hilos de java. Ademas desde el android 4 es obligatorio hacer muchas cosas en hilos fuera de la Activity, tarde o temprano tendrás que usarlo y mucho. El AsyncTask tiene el método onProgressUpdate(String... values) que puedes llamarlo desde el doInBackground(Object... params) con un publishProgress(xxxxxxxxx). Así podrás mandar datos a la activity cuando pase algo que te interesa mostrar. Con el metodo onPostExecute(Boolean result) sabras cuando termino el AsyncTask, También accedes a la activity desde este método. Y para terminar un AsyncTask yo no uso finish(), no se como no te da error eso. Posiblemente no haga nada. debes utilizar el método de cancel(true). Pero ten cuidado por que puede que ya haya terminado y te dará error. Hazlo con esta condición y no da problemas. if (registro.getStatus() == AsyncTask.Status.RUNNING){ registro.cancel(true); } Suerte ;) |
#5
|
||||
|
||||
Entiendo todo lo que me decís pero creo que no me sirve ninguna voy a intentar explicar concretamente como uso el hilo a ver si podeis ayudarme un poco mas, de cualquier forma os agradezco el interes.
El caso es que yo cuando llamo al finish() desde el hilo principal (que activa un flag para salir del bucle principal del AsyncTask), uso unos datos que procesa este hilo, entonces justo despues de finish() necesito esperar a que el AsyncTask termine la última iteración del bucle y guarde los datos procesados en otra clase, (lo que desde la versión de escritorio del mismo programa hago con un join() en el hilo principal), para seguir el flujo normal del programa. Uso finish() en lugar de cancel(true) simplemente porque con cancel(true) pierdo la posibilidad de comprobar la variable status de AsyncTask. La verdad es que este problema me trae un poco de cabeza, porque solucionandolo casi daria por acabado mi proyecto final de carrera y a disfrutar entonces de lo que queda de verano, pero no se si me explico del todo bien para que podais ayudarme, de todas formas muchisimas gracias. Saludos |
#6
|
||||
|
||||
Igual sigo sin entenderlo, pero ese código que quieres ejecutar después de darle al botón que hace el finish() es el que tiene que ir en el onPostExecute, que para eso está.
O, como proponían antes, con un Handler. Cuando recibas el mensaje de que el hilo ha terminado, continúas.
__________________
El mejor Cuatro en Raya de Android (Hilo en HTCMania, Play Store) ¡Un millón de descargas!
|
#7
|
||||
|
||||
bueno por lo que puedo entender lo que quieres es:
poner un boton en la activity que al presionarlo tome los datos que se han estado calculando en un AsyncTask. Posteriormente cerrar ese AsyncTask. Supongo que el AsyncTask es un subclase dentro de la activity. Yo lo haria: - Declarando las variables de los resultados como globales dentro de la activity. - En el AsyncTask publica los valores de las resultados en el onProgressUpdate, así te aseguras que se calcularon bien los datos, que no se toman datos a mitad de calculo. - Cuando presiono el boton ese, leer los datos de las variables globales y después cerrar el AsyncTask si es necesario. (puede ser mejor al revés, así te aseguras que termina el proceso del AsyncTask, primero cierralo y despues lee las variables, depende del proceso de calculo que este dentro del AsyncTask) - Si necesitas un aviso de que termino el AsyncTask, ponlo en el método onPostExecute(Boolean result) del AsyncTask. Así accedes a los resultados cuando quieras. Te aseguras que no se actualizan los resultados sin haber completado una vuelta entera del proceso del AsyncTask. Si se termina el AsyncTask te avisa sin necesidad de comprobar el estado. No se si es lo que querías hacer. Sino es eso mándame un privado y lo vemos con el código. |
#8
|
||||
|
||||
Pues sigo sin conseguirlo, el caso es que el hilo toca parte de la interfaz y el boton que lo para, ademas de pararlo lo vuelve arrancar, entonces justo antes de arrancarlo tengo que estar seguro de que esta acabado, para eso necesito un metodo parecido al join... para antes de instanciar de nuevo el hilo y ejecutarlo me asegure que el anterior no esta todavia calculando y mostrando en la interfaz, que creo que es cuando la aplicacion muere.
De todas formas seguire probando... |
#9
|
||||
|
||||
Para estar seguro de que ha acabado necesitas el onPostExecute, que ya se ejecuta en el hilo principal (UI Thread). Cuando le des al botón de parar, le mandas parar al async task poniendo su flag running a false (o la que uses). Cuando acaba, en el onPostExecute metes el código que sea que quieres ejecutar, sabiendo que está acabado y que estás en el hilo principal. Ahí actualizas la interfaz y lanzas otro asynctask si quieres.
O sigo sin entenderlo ![]()
__________________
El mejor Cuatro en Raya de Android (Hilo en HTCMania, Play Store) ¡Un millón de descargas!
|
#10
|
||||
|
||||
jeje, no sigues sin entenderme del todo, pero voy a seguir probando otras opciones y si no consigo nada, en unos dias lo explicaré de nuevo lo mejor que pueda.
Saludos y gracias por la labor! |
![]() |
![]() |
||||||
|
Herramientas | |