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");