19

I have used AsyncTasks with my application, in order to lazy download and update the UI.

For now my AsyncTasks updates the UI real simply:

protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        gender.setText(values[0]);
}

My problem is how to check if the activity which the gender TextView rendered from, is still available?

If not, I will get an error and my application will shut down.

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
Asaf Nevo
  • 11,338
  • 23
  • 79
  • 154

8 Answers8

26

You can cancel your asynctask in the activity's onDestroy

@Override
protected void onDestroy() {
    asynctask.cancel(true);
    super.onDestroy();
}

and when performing changes you check whether your asynctask has been cancelled(activity destroyed) or not

protected void onProgressUpdate(String... values) {
    super.onProgressUpdate(values);
    if(!isCancelled()) {
         gender.setText(values[0]);
    }
}
ColdFire
  • 6,764
  • 6
  • 35
  • 51
  • Nice. But there's no guranttee that ondestroy will get called everytime. (For reference link below). How do you cope with that ? https://stackoverflow.com/a/4449988/3265444 – Ajji Feb 06 '18 at 10:35
9

I had a similar problem - essentially I was getting a NPE in an async task after the user had destroyed the fragment. After researching the problem on Stack Overflow, I adopted the following solution:

volatile boolean running;

public void onActivityCreated (Bundle savedInstanceState) {

    super.onActivityCreated(savedInstanceState);

    running=true;
    ...
    }


public void onDestroy() {
    super.onDestroy();

    running=false;
    ...
}

Then, I check "if running" periodically in my async code. I have stress tested this and I am now unable to "break" my activity. This works perfectly and has the advantage of being simpler than some of the solutions I have seen on SO.

IanB
  • 3,489
  • 1
  • 20
  • 24
  • 2
    This is simple and really makes sense :) If anyone's thinking about that `volatile` keyword, read this: http://stackoverflow.com/a/107040/4331787 – Mohit Singh Dec 14 '16 at 14:22
4

Try

if (!isFinishing()) {
    gender.setText(values[0]);
}
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Jaiprakash Soni
  • 4,100
  • 5
  • 36
  • 67
2

Check whether activity is running or not

 if (!isFinishing()) {
  // Do whatever you want to do
}
Emran Hamza
  • 3,829
  • 1
  • 24
  • 20
1

Even though, I have never faced this scenario; I will try to answer your question.

In your case you will need to validate the Context passed to AsyncTask.

You can perform validation

if(null!=mContext)  //Activity still exist!!
{
  gender.setText(values[0]);
}
else //Activity is destroyed
{
   //Take appropriate action!!
}  

The advantage will be, if the activity is destroyed by the time you reach this statement, your Context will automatically become null and you can handle the scenario.

t0mm13b
  • 34,087
  • 8
  • 78
  • 110
Vipul
  • 27,808
  • 7
  • 60
  • 75
  • 2
    This will not work. Because you keep hard-reference to the activity, it will not be nulled. It will become invalid, but async task will continue to keep reference to the activity. – uthark Sep 25 '13 at 17:44
1

I will insist that you that if you Activity is not running why don't you cancel the AsyncTask? That would be a better and feasible solution. If you Application is running say you move from one Activity to another then it won't give error AFAIK.

But, I would insist to cancel the AsyncTask then you'r Activity is not running, you can check AsyncTask is running or not,

if(task != null && task.equals(AsyncTask.Status.RUNNING))
task.cancel(true);
Lalit Poptani
  • 67,150
  • 23
  • 161
  • 242
1

As this part of one training on Android Developers suggests, keep a WeakReference on the UI element that needs to be updated after task is done and check if the reference is null before using it. This helps not only in checking if the UI is still around, but also does not prevent UI elements from being garbage collected.

frangulyan
  • 3,580
  • 4
  • 36
  • 64
0

Shouldn't

if (gender) {
   gender.setText(values[0]);
}

be enough?

uvesten
  • 3,365
  • 2
  • 27
  • 40
  • are you taking for (null==gender)? even for that, no only that's not enough some time – Dheeresh Singh Jun 25 '12 at 12:52
  • 1
    No, that's not enough. The activity may be finished but gender may still be non-null, and attempts to reference it will fail because the View/Window is no longer active. – Thinkisto Apr 10 '13 at 09:47