0

My code runs fine, but if I go back to the home screen and return the code stops running on the text view shows nothing. Shouldn't it restart when I return to the page? It throws no errors, but if I eliminate the task and initialize the app it all over again it works but I must stay on that activity because If I go to Home and return it stops.

public class IsstatusActivity extends AppCompatActivity {

    JSONParser jsonparser = new JSONParser();
    TextView latitude;
    TextView longitude;
    String lat;
    String longit;
    JSONObject jobj = null;

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition tryAgain = lock.newCondition();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.isstatus);
        latitude = (TextView) findViewById(R.id.Coordinates);
        longitude = (TextView) findViewById(R.id.longitude);


        new Retrievedata().execute();
    }

    class Retrievedata extends AsyncTask<Void, String, Void> {


        @Override
        protected Void doInBackground(Void... params) {

            try {

                while (!isCancelled()) {

                    jobj = jsonparser.makeHttpRequest("http://api.wheretheiss.at/v1/satellites/25544");

                    String lat = "latitude : " + jobj.getString("latitude");
                    String longit ="longitude : " + jobj.getString("longitude");

                    // this will cause onProgressUpdate to be called with lat & long
                    publishProgress(lat,longit);

                    // it's okay to sleep within the background thread
                    Thread.sleep(1500);

                }

            } catch (InterruptedException e) {
                Log.w("RetrieveData", "thread was interrupted", e);
            } catch (JSONException e) {
                Log.e("RetrieveData", "parse error", e);
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            latitude.setText(values[0]);
            longitude.setText(values[1]);
        }
    }
}
K Neeraj Lal
  • 6,768
  • 3
  • 24
  • 33

1 Answers1

0

Shouldn't it restart when I return to the page?

Not necessarily. From the AsyncTask documentation:

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

So by default the execution of AsyncTasks on versions of Android from Honeycomb onwards is serialised, meaning that only one can execute at any given time.

Looking at Retrievedata, it is set up to loop until it is cancelled (or it is interrupted or encounters a JSON related exception). However, the task isn't ever cancelled in IsstatusActivity (say, in onDestroy()), so barring interruptions or errors it will run forever (or at least until your app is killed).

Part of the reason for this is that AsyncTasks are not tied to the activity lifecycle. That means that they don't get automatically stopped when the activity they were created in finishes - rather, they keep on running until they finish whatever they're tasked with doing. Again, because Retrievedata loops until it's cancelled and this never happens, it will happily block the execution of new instances of Retrievedata created when the IsstatusActivity is subsequently started again (not to mention any other AsyncTask instances you may be using in other activities).

For more background I recommend checking out:

You may be able to solve the issue by cancelling the task when you finish the activity, but as other posters have stated it may be better to avoid using AsyncTask at all for this kind of task. My understanding of AsyncTask is that it is best used for short running operations - indeed, this is what the documentation says:

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

As an aside, there's another issue with the code posted. As Retrievedata is an inner class (as opposed to being static) of IsstatusActivity, each instance of it will keep an implicit reference to the instance of IsstatusActivity it was created in. This means that even after you finish any given instance of IsstatusActivity, it will remain in memory until the Retrievedata instance created within it has finished and can be garbage collected. As per the above, this will never happen because the task runs forever.

This is called activity/context leaking. Every time IsstatusActivity is started and finished, the instance will hang around consuming memory until the app is killed. Activities are heavy objects so this is definitely something to be avoided.

Hope that helps!

Community
  • 1
  • 1
clownba0t
  • 1,103
  • 10
  • 12