Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Handling back button during asynctask

Tags:

android

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
like image 445
aperture Avatar asked Mar 15 '11 20:03

aperture


2 Answers

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);
like image 114
aperture Avatar answered Oct 18 '22 04:10

aperture


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.

like image 25
CommonsWare Avatar answered Oct 18 '22 04:10

CommonsWare