Called From Wrong Thread Exception with AsyncTask

9.3k views Asked by At

I keep getting a CalledFromWrongThreadException even if i throw it into AsyncTask's DoInBackground method! Can anyone tell me why and how to fix it?

/**
     * 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);
        }
    }

this is my AsyncTask class

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) {}
}

Here's the stacktrace I got:

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
3

There are 3 answers

3
Codeman On BEST ANSWER

Try wrapping your file access code with runOnUIThread(new Runnable{/*code goes here*/}())

1
ChristopheCVB On

You can use onPostExecute which runs on the UI thread... It's the basic of using asynctask.

0
Zambotron On

The reason you are getting this exception is because your are trying to update the UI in the doInBackground() method of your AsyncTask. This is happening when you set the adapter for your listview here: notesListView.setAdapter(arrayAdapter); //refreshes the listView

You should move this to onPostExecute. Update the UI in onPostExecute and display any error messages if necessary.

Also note that you are calling handleCommand() in the background as well; make sure that this isn't going to update the UI as well!