Llamado desde una excepción de subproceso incorrecto con AsyncTask

¡Sigo recibiendo una CalledFromWrongThreadException incluso si la lanzo al método DoInBackground de AsyncTask! ¿Alguien puede decirme por qué y cómo solucionarlo?

/**
     * Recognizes key words in responseTexts and runs the appropriate function
     * @param responseText
     */
    private void responseHandler(String responseText) {
        if(responseText.startsWith("Notes", 0)) {
            notes.add(responseText);
            new DownloadFilesTask().execute("WriteInternal" , null, null);
        }
    }

esta es mi clase AsyncTask

private class DownloadFilesTask extends AsyncTask<String, Void, String> {
    protected String doInBackground(String... command) {
    if(command[0].equals("WriteInternal") {
        //write to internal storage
    FileOutputStream fOut = null;
    OutputStreamWriter osw = null;
    try{
        fOut = openFileOutput("notes.txt", Context.MODE_PRIVATE);
        osw = new OutputStreamWriter(fOut);
        for (int i = 0; i < notes.size(); i++){
            osw.write(notes.get(i) + "\n");
        }
        osw.close();
        fOut.close();
    } catch(Exception e) {
        e.printStackTrace(System.err);
    }

    notesListView.setAdapter(arrayAdapter);  //refreshes the listView

       }
else {
        sendCommand(command[0]);
        return null;
}
    }

    protected void onProgressUpdate(Void... progress) {}
    protected void onPostExecute(String result) {}
}

Aquí está el stacktrace que obtuve:

05-22 15:14:20.370: E/AndroidRuntime(11730): FATAL EXCEPTION: AsyncTask #2
05-22 15:14:20.370: E/AndroidRuntime(11730): java.lang.RuntimeException: An error occured while executing doInBackground()
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.os.AsyncTask$3.done(AsyncTask.java:278)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.lang.Thread.run(Thread.java:856)
05-22 15:14:20.370: E/AndroidRuntime(11730): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4039)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.ViewRootImpl.invalidateChild(ViewRootImpl.java:722)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:771)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:4005)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.View.invalidate(View.java:8576)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.view.View.invalidate(View.java:8527)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.widget.AbsListView.resetList(AbsListView.java:1734)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.widget.ListView.resetList(ListView.java:502)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.widget.ListView.setAdapter(ListView.java:442)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at com.nelson.jarvisclientics.Notes$DownloadFilesTask.doInBackground(Notes.java:281)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at com.nelson.jarvisclientics.Notes$DownloadFilesTask.doInBackground(Notes.java:1)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
05-22 15:14:20.370: E/AndroidRuntime(11730):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-22 15:14:20.370: E/AndroidRuntime(11730):    ... 5 more

preguntado el 22 de mayo de 12 a las 20:05

También sería útil publicar el seguimiento de la pila que recibe al ejecutar este código. -

3 Respuestas

Intente envolver su código de acceso a archivos con runOnUIThread(new Runnable{/*code goes here*/}())

contestado el 22 de mayo de 12 a las 20:05

Solo una nota: podría ser mejor y más con los principios de diseño de Android hacer lo que otros han dicho y manejar esto en onPostExecute(). Simplemente almacene en caché su archivo, luego escríbalo en onPostExecute(). - codificador

No debe acceder a archivos en el subproceso de interfaz de usuario. notesListView.setAdapter(arrayAdapter) tiene que hacerse en el subproceso ui. Pero con AsyncTask lo haces en onPostExecute() que se ejecuta en el subproceso de la interfaz de usuario. - Dirk Jackel

Esto solucionó el problema que estaba teniendo, pero todavía no entiendo por qué. Estaba agregando elementos a mi lista en onProgressUpdate (que se ejecuta en el hilo de la interfaz de usuario) y obtuve esta excepción, cuando agregué esto se detuvo. - Igor Cordas

La razón por la que obtiene esta excepción es porque está intentando actualizar la interfaz de usuario en el método doInBackground() de su AsyncTask. Esto sucede cuando configura el adaptador para su vista de lista aquí: notesListView.setAdapter(arrayAdapter); //refreshes the listView

Debe mover esto a onPostExecute. Actualice la interfaz de usuario en onPostExecute y muestre cualquier mensaje de error si es necesario.

También tenga en cuenta que también está llamando a handleCommand() en segundo plano; ¡Asegúrate de que esto no va a actualizar la interfaz de usuario también!

contestado el 22 de mayo de 12 a las 20:05

Puede usar onPostExecute que se ejecuta en el subproceso de la interfaz de usuario... Es lo básico para usar asynctask.

contestado el 22 de mayo de 12 a las 20:05

Agregué un comentario a mi solución anterior sugiriendo que este es el mejor método. - codificador

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.