onprogressupdate oncancelled clase cancel bar asynctask android

android - oncancelled - publishProgress desde dentro de una función en doInBackground?



oncancelled asynctask android (5)

Utilizo una AsyncTask para realizar un proceso largo.

No quiero colocar mi código de proceso largo directamente dentro de doInBackground. En cambio, mi código de proceso largo está ubicado en otra clase, a la que llamo en DoInBackground.

Me gustaría poder llamar a publishProgress desde dentro de la función longProcess. En C ++ pasaría un puntero de devolución de llamada a publishProgress a mi función longProcess.

¿Cómo hago eso en java?

EDITAR:

Mi código de proceso largo:

public class MyLongProcessClass { public static void mylongProcess(File filetoRead) { // some code... // here I would like to call publishProgress // some code... } }

Mi código de AsyncTask:

private class ReadFileTask extends AsyncTask<File, Void, Boolean> { ProgressDialog taskProgress; @Override protected Boolean doInBackground(File... configFile) { MyLongProcessClass.mylongProcess(configFile[0]); return true; } }

EDITAR # 2 El método de proceso largo también podría ser no estático y llamado así:

MyLongProcessClass fileReader = new MyLongProcessClass(); fileReader.mylongProcess(configFile[0]);

Pero eso no cambia mi problema.


Si esto funciona, por favor hágamelo saber! Tenga en cuenta que llamar a doProgress desde cualquier lugar que no sea un método que ha sido invocado desde doInBackground es casi seguro que cause un error.

Si, funciona. Lo extendí para que no tenga que pasar AsyncTask como parámetro a su método. Esto es particularmente útil si (como yo) ya ha escrito todos sus métodos antes de decidir que realmente necesita publicar algún progreso, o en mi caso, actualizar la interfaz de usuario desde una AsyncTask:

public abstract class ModifiedAsyncTask<A,B,C> extends AsyncTask<A,B,C>{ private static final HashMap<Thread,ModifiedAsyncTask<?,?,?>> threads = new HashMap<Thread,ModifiedAsyncTask<?,?,?>>(); @Override protected C doInBackground(A... params) { threads.put(Thread.currentThread(), this); return null; } public static <T> void publishProgressCustom(T... t) throws ClassCastException{ ModifiedAsyncTask<?, T, ?> task = null; try{ task = (ModifiedAsyncTask<?, T, ?>) threads.get(Thread.currentThread()); }catch(ClassCastException e){ throw e; } if(task!=null) task.publishProgress(t); } } public class testThreadsActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } public void Button1Clicked(View v){ MyThread mthread = new MyThread(); mthread.execute((Void[])null); } private class MyThread extends ModifiedAsyncTask<Void, Long, Void>{ @Override protected Void doInBackground(Void... params) { super.doInBackground(params); while(true){ myMethod(System.currentTimeMillis()); try { Thread.sleep(1000L); } catch (InterruptedException e) { return null; } } } protected void onProgressUpdate(Long... progress) { //Update UI ((TextView) findViewById(R.id.textView2)).setText("The Time is:" + progress[0]); } } private void myMethod(long l){ // do something // request UI update ModifiedAsyncTask.publishProgressCustom(new Long[]{l}); } }

Me parece bastante sucio, ¿alguien más tiene una mejor manera?

Mi camino es probablemente peor. Estoy llamando a un método estático para doProgress (al que llamé publishProgressCustom). Se puede llamar desde cualquier lugar sin producir un error (como si el subproceso no tiene una AsyncTask correspondiente en el hashMap, no llamará publishProgress). La desventaja es que usted debe agregar la asignación Thread-AsyncTask una vez que el hilo haya comenzado. (No puede anular AsyncTask.execute () tristemente ya que esto es definitivo). Lo he hecho aquí al anular doInBackground () en la súper clase, de modo que cualquiera que lo extienda solo tiene que poner super.doInBackground () como primera línea en su propio doInBackground ().

No sé lo suficiente sobre Threads y AsyncTask para saber qué sucede con las referencias de HashMap una vez que Thread y / o AsyncTask llegan a su fin. Sospecho que suceden cosas malas, por lo que no sugeriría que nadie intente mi solución como parte de la suya a menos que sepan mejor.


Cuando dices " mi código de proceso largo está ubicado en otra clase a la que llamo en DoInBackground ", ¿te refieres a " ubicado en otro método que llamo en DoInBackground "?

Si es así, podrías hacer que ese método sea un método privado de tu clase AsynTask. Luego, puede llamar a publishProgress dentro del método cuando sea necesario.


La dificultad es que publishProgress está protected final por lo que incluso si pasa this a su método static , aún no puede llamar a publishProgress directamente.

No lo he intentado yo mismo, pero ¿qué tal?

public class LongOperation extends AsyncTask<String, Integer, String> { ... @Override protected String doInBackground(String... params) { SomeClass.doStuff(this); return null; } ... public void doProgress(int value){ publishProgress(value); } } ... public class SomeClass { public static void doStuff(LongOperation task){ // do stuff task.doProgress(1); // more stuff etc } }

Si esto funciona, por favor hágamelo saber! Tenga en cuenta que llamar a doProgress desde cualquier lugar que no sea un método que ha sido invocado desde doInBackground es casi seguro que cause un error.

Me parece bastante sucio, ¿alguien más tiene una mejor manera?


Una solución podría ser colocar una clase public simple dentro de AsyncTask (asegúrese de que la tarea que defina también sea public ) que tenga un método public que llame publishProgress(val) . Pasar esa clase debe estar disponible desde cualquier otro paquete o clase.

public abstract class MyClass { public MyClass() { // code... } // more code from your class... public class Task extends AsyncTask<String, Integer, Integer> { private Progress progress; protected Task() { this.progress = new Progress(this); } // ... @Override protected Integer doInBackground(String... params) { // ... SomeClass.doStuff(progress); // ... } // ... @Override protected void onProgressUpdate(Integer... progress) { // your code to update progress } public class Progress { private Task task; public Progress(Task task) { this.task = task; } public void publish(int val) { task.publishProgress(val); } } } }

y luego en la otra clase:

public class SomeClass { public static void doStuff(Progress progress){ // do stuff progress.publish(20); // more stuff etc } }

Esto funcionó para mí.


longProcess() función longProcess() en funciones más pequeñas.

Código de muestra:

@Override protected Boolean doInBackground(Void... params) { YourClass.yourStaticMethodOne(); publishProgress(1); YourClass.yourStaticMethodTwo(); publishProgress(2); YourClass.yourStaticMethodThree(); publishProgress(3); // And so on... return true; }