3

This MAY be a duplicate of another question, I am not sure. I've read similar questions, but either wasn't able to make sense of it, or wasn't able to successfully apply the given solutions.

I've created an application that has multiple tabs. Most tabs use an ASyncTask to update data when the users slides into the tab. However, when something about the activity changes while the AST is still running (that happens a lot; eg when the user rotates the screen or exits using the back button), the application will force close (ANR).

Here's what I see happening in my LogCat:

10-30 11:30:01.422: E/AndroidRuntime(4687): FATAL EXCEPTION: main
10-30 11:30:01.422: E/AndroidRuntime(4687): java.lang.NullPointerException
10-30 11:30:01.422: E/AndroidRuntime(4687):     at com.appconstructor.khcreates.Core$refreshList.onPostExecute(Core.java:913)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at com.appconstructor.khcreates.Core$refreshList.onPostExecute(Core.java:1)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.os.AsyncTask.finish(AsyncTask.java:631)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.os.Handler.dispatchMessage(Handler.java:99)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.os.Looper.loop(Looper.java:137)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at android.app.ActivityThread.main(ActivityThread.java:4745)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at java.lang.reflect.Method.invokeNative(Native Method)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at java.lang.reflect.Method.invoke(Method.java:511)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-30 11:30:01.422: E/AndroidRuntime(4687):     at dalvik.system.NativeStart.main(Native Method)

From what I can see, the ASyncTask (refreshlist) can't handle the fact that there's no application left to apply the change to.

What I want to do is make an application that doesn't force close if there's no activity.

  1. EITHER I want the ASyncTask to stop if the activity stops
  2. OR I want the application to just keep the task running, but not force close (eg: nothing happens onPostExecute() if there's no activity connected.

If someone needs my onPostExecute() code to solve the problem, let me know.

This has been bugging me for a while, and I haven't been able to solve this for myself. My app's experience is pretty horrible with this bug in place. Help would VERY much be appreciated!

Thanks in advance!

Vic V
  • 1,080
  • 2
  • 12
  • 31

2 Answers2

9

Keep a reference to your task, and in the onDestroy and onConfigurationChanges methods, cancel the task..

if(task != null && task.getStatus() == Status.RUNNING)
    task.cancel(true);
Nermeen
  • 15,883
  • 5
  • 59
  • 72
  • I'm currently trying that, but maybe I'm doing it wrong. I'm setting a reference to the task `onPreExecute()` like `AST = this;` and `onConfigurationChanged` I call `AST.cancel(true);`, but the crash still occurs. – Vic V Oct 30 '12 at 10:56
  • 1
    in your onPostExecute, try to add if(isCancelled()) return; – Nermeen Oct 30 '12 at 11:13
  • Thanks for the updated code samples. I've created a paste with what I'm currently doing (it still force closes). Maybe you can see what I'm doing wrong? http://pastebin.com/SBYGiexG EDIT - Also, there may be more than one instance of refeshList running (because I use viewpager): could the error be there? – Vic V Oct 30 '12 at 11:24
  • Could you provide full code of your activity and asynctask? EDIT:If AST is a static reference, yes this could be a problem – Evos Oct 30 '12 at 11:27
  • The activity is extremely long (it does a lot of things). The logcat is still the same http://pastebin.com/9bZJme3V . Here's onPostExecute http://pastebin.com/ae3AxvRc and here's how it's usually called http://pastebin.com/HyjS7wc5 (I say usually because it can also be called from the menu, in a similar way) – Vic V Oct 30 '12 at 11:32
  • And @Evos, regarding your edit, there's only one reference. What would be the best way to do it? I THINK there can be max 3 (current tab and both tabs to the side) at the same time, but it may be indefinite if a user is swiping between tabs quickly.. – Vic V Oct 30 '12 at 11:35
  • 1
    You need to store instance of your AsyncTask individualy in each fragment, so save instacne of `new freshList(this,getActivity(),mNum)` as you fragment's variable and, since this is a fragment, execute `cancel(true)` in `onPause()` method of your fragments. Hope this will help you. – Evos Oct 30 '12 at 11:39
  • This did it! Thanks so much! I will mark your answer as the solving one and just plus all the helpful answers by Nunu. Thanks so much to the both of you! – Vic V Oct 30 '12 at 11:49
4

It's better to execute cancel(true) with same instance that you used for execute() command:

AsyncTask<Void,Void,Void> task = new MyAsyncTask();
task.execute();

.....

task.cancel(true);

EDIT:You need to store instance of your AsyncTask individualy in each fragment, so save instance of new freshList(this,getActivity(),mNum) as you fragment's variable and, since this is a fragment, execute cancel(true) in onPause() method of your fragments. Hope this will help you.

Evos
  • 3,915
  • 2
  • 18
  • 21
  • Although this did the trick, see the discussion under Nunu's answer for the answer specific to my case (fragments). – Vic V Oct 30 '12 at 11:51