简体   繁体   中英

What happens in memory when the Activity is destroyed while its AsyncTask is running?

I've been playing around with an app I created.

  1. Activity A(1st Activity) has a button that executes an AsyncTask. This AsyncTask's doInBackground() performs calculations on selected values in Activity A, and its onPostExecute() starts Activity B.

  2. I click the button, then before Activity B can be started I press back to destroy Activity A.

  3. The app closes, then relaunches with Activity B populated with calculations from my AsyncTask.

this awesome blog explains memory leaks with Threads when the screen is rotated, and I'm applying those lessons here with my AsyncTask and back button press. However, I'm still a little confused.

  1. Pressing back on an Activity destroys it.

  2. My asynctask is running on an activity that was destroyed, should throw a NPE since it's accessing list elements inside that activity.

  3. But it didn't. What does destroyed really mean then? I thought it meant that the Activity A reference and its view hierarchy would be set to null to allow the garbage collector to sweep it up sometime and recycle the memory. The blog states it didn't, hence the memory leak.

So wait, Activity A didn't get destroyed? But I saw it disappear...

This is a conceptual question rather than a code question so far, but as requested:

private class MyAsyncTask extends AsyncTask<ArrayList<Train>, Void, Void> {

    protected void onPreExecute() {
        // Runs on the UI thread before doInBackground
        spinWait.setVisibility(ProgressBar.VISIBLE);
        waitMsg.setText("Calculating Schedules....");

        spinWait.bringToFront();
        waitMsg.bringToFront();
    }


    @Override
    protected Void doInBackground(ArrayList<Train>... lolTrains) {

        try {
            calcSchedules(lolTrains[0]);
        } catch (Exception e) {
            Log.d("DEBUG", "Calculating schedules failed, " + e.getMessage());
        }
        return null;
    }


    @Override
    protected void onPostExecute(Void v) {
        // This method is executed in the UIThread
        spinWait.setVisibility(View.GONE);
        waitMsg.setVisibility(View.GONE);

        // if schedules is empty, show error dialog
        if (schedules.size() == 0) {
            // show msg, etc
        } else {
            Intent i = new Intent(getBaseContext(), ResultsActivity.class);
            i.putExtra("results", schedules);
            startActivity(i);
        }
    }
}

public void MethodInActivityA(View v) {
    new MyAsyncTask().execute(memberVarInActivityA);
}

When you destroyed your activity, you did not destroy you AsyncTask (which is basically kind of a Thread ), to do that try

asyncTask.cancel(true);

on your onDestroy(); method

hope this helps

On your onPostExecute() , When start new activity call finsih() followed by startActivity(i) . This finish() internally call onDestroy . Here you need to clear Asynctask manually because Asynctask is inner class of your Activity. Even activity was destroyed this inner class holds the reference of activity. You need manually clear the reference by asyncTask.cancel() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM