publishprogress oncancelled example clase cancel asynctask android multithreading android-asynctask handler

oncancelled - Android runOnUiThread/AsyncTask no puede resolver CalledFromWrongThreadException



execute asynctask android (3)

Estoy trabajando para una aplicación de Android e implementando una ProgressBar utilizando la clase AsyncTask.

El problema es que en algunos dispositivos causa "CalledFromWrongThreadException: solo el hilo original que creó una jerarquía de vistas puede tocar sus vistas". en onPostExecute. En esos dispositivos, el problema ocurre 100%. En otros dispositivos, funciona bien.

public final class MyAsyncTask extends AsyncTask<String, Integer, String> { private ProgressBar progress; private ListActivity activity; public MyAsyncTask(ListActivity activity, ProgressBar progress) { this.progress = progress; this.activity = activity; } protected void onPreExecute() { this.progress.setVisibility(view.VISIBLE); } protected String doInBackground(String[] arg0) { // getting xml via httpClient return string; } protected void onPostExecute(String result) { this.progress.setVisibility(view.GONE); }

No entiendo por qué onPostExecute no se ejecuta en el hilo de UI, en esos dispositivos determinados.

Luego, traté de llamarlo con runOnUiThread, para estar absolutamente seguro de que se ejecuta en el subproceso de UI.

runOnUiThread(new Runnable() { @Override public void run() { ProgressBar progress = (ProgressBar)findViewById(R.id.some_view_progressbar); MyAsyncTask task = new MyAsyncTask(activity, progress); task.execute(); } } );

Incluso esto no resolvió el problema. La misma excepción todavía ocurre.

Desde Log, confirmé que Thread.currentThread (). GetId () es ciertamente diferente del hilo de la actividad principal de la aplicación dentro del controlador.

Estoy atascado. Cualquier consejo será apreciado.

NOTA: edité el código de muestra (no un código real) para corregir el nombre del método equivocado y la "cadena de retorno" que faltaba. Agregaré más información más tarde.


Escriba un controlador en el hilo de la interfaz de usuario y llame al controlador desde onPostExecute. Solucionará el problema.

Algo como esto. Tener un controlador en el hilo de UI (hilo principal):

handler = new Handler(){ @Override public void handleMessage(Message msg) { //run on UI Thread } };

y llame aPostExecute () de esta manera:

handler.sendEmptyMessage(MSG);


Asegúrese de estar invocando a aysnctask.execute () solo desde el hilo principal.


No veo nada malo con MyAsyncTask sí mismo, pero todavía hay otras cosas que pueden salir mal.

Iniciando AsyncTask

De los documentos de Android

Enhebrar las reglas

Hay algunas reglas de enhebrado que se deben seguir para que esta clase funcione correctamente:

  • La clase AsyncTask debe cargarse en el subproceso UI. Esto se hace automáticamente a partir de JELLY_BEAN.
  • La instancia de la tarea debe crearse en el hilo de la interfaz de usuario.
  • execute (Params ...) debe invocarse en el subproceso UI.
  • No invoque onPreExecute (), onPostExecute (Result), doInBackground (Params ...), onProgressUpdate (Progress ...) manualmente.
  • La tarea se puede ejecutar solo una vez (se lanzará una excepción si se intenta una segunda ejecución).

No muestra dónde crea la instancia normalmente y ejecuta la tarea, por lo tanto, asegúrese de hacerlo en un código que ya esté en la interfaz de usuario / hilo principal. Tenga en cuenta que el primer punto anterior podría explicar por qué esto funciona para usted en algunos dispositivos, y no en otros.

Crear la jerarquía de vista

El mensaje te dice

Solo el hilo original que creó una jerarquía de vistas puede tocar sus vistas.

y supones que esto se debe a que tu tarea asincrónica está (extrañamente) tratando de modificar la interfaz de usuario en una cadena de fondo. Sin embargo, es posible que obtenga este error porque la tarea asincrónica modifica la interfaz de usuario en el hilo principal, pero la interfaz de usuario ( ProgressBar ) no se creó correctamente en primer lugar.

Consulte esta pregunta para ver un ejemplo de cómo puede crear erróneamente la vista en el hilo equivocado (cualquier cosa que no sea el hilo principal ) y obtener el mismo error.

Más

Sin embargo, me gustaría ver exactamente dónde está registrando el ID del hilo y qué valor (es) está obteniendo. Si revisas mis dos primeras sugerencias y no resuelven tu problema, es posible que necesitemos más información.

También mencionas un Manejador (?), Pero no muestras cómo ni dónde lo usas. Normalmente, el uso de AsyncTask elimina la necesidad de usar Handler , por lo que estoy un poco preocupado acerca de cómo podría estar usando eso.

Actualizar

Según la discusión en los comentarios a continuación, parece que el problema aquí es el que se discute en esta pregunta . Algún código, probablemente ejecutándose en un hilo de fondo, es el primero en causar que se AsyncTask clase AsyncTask . La implementación original (pre-Jelly Bean) de AsyncTask requería que la carga de clase ocurriera en el hilo principal (como se menciona en las Reglas de subprocesamiento anteriores). La solución simple es agregar código en el hilo principal (por ejemplo, en Application#onCreate() ) que fuerza la carga de clase determinista temprana de AsyncTask :

Class.forName("android.os.AsyncTask");