14
votes

I have an Activity that shows a listview. On item click a second activity is started which runs an AsyncTask that fetches a remote URL based on which item is clicked, parses the results, then displays those results into another list view. While the async task is running I have a "loading" view that just displays an image and text. The problem is if I initiate the activity that runs the async task, then press back and start another instance of said activity, I get a force close.

I have tried

private class getlist extends AsyncTask implements OnDismissListener{
     ...
     @Override
     public void onDismiss(DialogInterface arg0) {
          this.cancel(true);
     }
}

But the problem persists.

I have also put

if(!isCancelled()){
  setContentView(R.layout.list);
  ...
  etc.

}

into my onPostExecute call, but either this is not preventing the view from being switched, or the problem is something else.

logcat shows "unexpected resume while already resumed .. got RemoteException sending setActive(false) notification" Then a bit further down in the log, "java.net.SocketTimeoutException: Socket is not connected"

How can I resolve this?

update:

E/AndroidRuntime(19379): Uncaught handler: thread AsyncTask #2 exiting due to uncaught exception
E/AndroidRuntime(19379): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(19379):        at android.os.AsyncTask$3.done(AsyncTask.java:200)
E/AndroidRuntime(19379):        at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
E/AndroidRuntime(19379):        at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
E/AndroidRuntime(19379):        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
E/AndroidRuntime(19379):        at java.util.concurrent.FutureTask.run(FutureTask.java:137)
E/AndroidRuntime(19379):        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
E/AndroidRuntime(19379):        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
E/AndroidRuntime(19379):        at java.lang.Thread.run(Thread.java:1096)
E/AndroidRuntime(19379): Caused by: java.lang.NullPointerException
E/AndroidRuntime(19379):        at com.metatroid.android.swim.ThreadViewer.getPosts(ThreadViewer.java:153)
E/AndroidRuntime(19379):        at com.metatroid.android.swim.ThreadViewer$getlist.doInBackground(ThreadViewer.java:70)
E/AndroidRuntime(19379):        at com.metatroid.android.swim.ThreadViewer$getlist.doInBackground(ThreadViewer.java:1)
E/AndroidRuntime(19379):        at android.os.AsyncTask$2.call(AsyncTask.java:185)
E/AndroidRuntime(19379):        at java.util.concurrent.FutureTask$Sync.innerRun
2
Your error, if you are reading LogCat correctly, has nothing to do with any of this, but rather is a network problem when you are trying to download the data.CommonsWare
@CommonsWare - I've updated the question with what I believe is the correct traceaperture

2 Answers

38
votes

The actual solution to this problem was to use ThreadSafeClientConnManager for the ClientConnectionManager

e.g.

BasicHttpParams params = new BasicHttpParams();
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
DefaultHttpClient httpclient = new DefaultHttpClient(cm, params);
6
votes

Do not access the activity from doInBackground(). It is only safe to access the activity in onPostExecute(), publishProgress(), or onPreExecute(), and even then only with some care to handle configuration changes, etc.

I would recommend that you make getlist be a static inner class, rather than a regular inner class. Manually associate the task and the activity, and break that association when the activity is destroyed or its configuration is changed. Your onPostExecute() and kin should then check to ensure that it has a valid activity before trying to use it.

This sample application demonstrates part of this -- handling the configuration change. It does not explicitly handle the BACK button scenario, but it does not need to, as it merely updates an activity that is off-screen.

In terms of why getPosts() has a NullPointerException, that is up to you to determine.