0

I am using a headless, retained task fragment to download and process data, so the UI thread is not blocked, and to gracefully handle configuration changes. The basic logic came from here and here, but, I made changes to allow working from a UI Fragment, instead of UI Activity.

It works. My only issue is that, on recovery -- after my app has been killed by the system -- the task fragment is running when it should not be. For this type of recovery, I have restored data from persistent storage, and do not want to download again. Note, though, that this superfluous running of the task fragment only happens if I have previously clicked refresh, thus creating a first use of the task fragment.

Here's where I'm working with the task fragment:

private static final String TAG_TASK_FRAGMENT = "task_fragment_2";
private static httpGetFragment mTaskFragment;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setHasOptionsMenu(true);

    System.err.println("onCreate ++++++++++++++");

    // setup for headless task fragment; the rest is in runTaskFragment()
    FragmentManager fm = getFragmentManager();
    mTaskFragment = (httpGetFragment) fm.findFragmentByTag(TAG_TASK_FRAGMENT);

    // If the Fragment is non-null, then it is currently being
    // retained across a configuration change; sort of... it's non-null more than expected

    if (mTaskFragment != null) {
        System.err.println("mTaskFragment is NOT null. Tag = " + mTaskFragment.getTag() + " >>>>>>>>>");
        mTaskFragment.setTargetFragment(this, 0); 
    }
}

And, starting it from a button click:

private void runTaskFragment() {

    System.err.println("----------- Running task fragment from action_refresh click !!!!!");

    setRefreshActionButtonState(true);

    FragmentManager fm = getFragmentManager();

    if (mTaskFragment == null) {
        mTaskFragment = new httpGetFragment();
        mTaskFragment.setTargetFragment(this, 0);
        fm.beginTransaction().add(mTaskFragment, TAG_TASK_FRAGMENT).commit();
    }
}

The onPostExecute() callback from the task fragment calls this:

private void finishTheRefresh(boolean successful) {

    if (mTaskFragment != null) mTaskFragment = null;
    System.err.println("&&&&&&&&&&& DONE !!! and mTaskFragment is NULL");

    setRefreshActionButtonState(false);
    if (successful) refreshDisplayList();
}

So, now to the logcat. Here's Kill revival, when refresh taskfragment has NOT previously been run, and it shows the desired behavior. Note that onNavigationItemSelected() is called by the system after actionBar setup in onResume(). BTW, restoring data from SD is happening in the Application Object:

01-07 09:35:05.549  27324-27324/com... W/ManagedEGLContext? doTerminate failed: EGL count is 2 but managed count is 1
01-07 09:36:05.314  30423-30423/com... W/System.err? restoring data from SD %%%%%%%%%%%%%%%%
01-07 09:36:05.366  30423-30423/com... W/System.err? onCreate ++++++++++++++
01-07 09:36:05.571  30423-30463/com... W/chromium? [WARNING:proxy_service.cc(890)] PAC support disabled because there is no system implementation
01-07 09:36:05.591  30423-30423/com... W/art? Attempt to remove local SIRT entry from IRT, ignoring
01-07 09:36:05.617  30423-30474/com... W/art? Thread[19,tid=30474,Native,Thread*=0x48ebca50,peer=0x6535eb38,"Thread-54625"] attached without supplying a name
01-07 09:36:05.664  30423-30423/com... W/System.err? onResume +++++++++++++++++++
01-07 09:36:05.847  30423-30423/com... W/System.err? *** onNavigationItemSelected -- where we need to go on kill-revival, to update list adapter ***
01-07 09:36:05.850  30423-30423/com... W/InputMethodManager? Ignoring onBind: cur seq=16255, given seq=16254
01-07 09:36:05.977  30423-30487/com... W/art? Thread[21,tid=30487,Native,Thread*=0x4cf57b88,peer=0x653a7610,"Thread-54627"] attached without supplying a name

Here, I do a refresh click:

01-07 09:40:08.480  30423-30423/com... W/System.err? &&&&&&&&&&& Refresh CLick !!!!!!!!!!!!!
01-07 09:40:08.483  30423-30423/com... W/System.err? ----------- Running task fragment from action_refresh click !!!!!
01-07 09:40:09.770  30423-30423/com... W/System.err? *** Post-Execute for data download & extraction ***
01-07 09:40:09.772  30423-30423/com... W/System.err? &&&&&&&&&&& DONE !!! and mTaskFragment is NULL

And, the problem Kill revival, where data has been downloaded. There's been no button click, and the taskfragment onPostExecute() callback has run. How can this happen, when I've previously nulled the taskfragment?

01-07 09:42:41.182  31645-31645/com... W/System.err? restoring data from SD %%%%%%%%%%%%%%%%
01-07 09:42:41.220  31645-31645/com... W/System.err? onCreate ++++++++++++++
01-07 09:42:41.220  31645-31645/com... W/System.err? mTaskFragment is NOT null. Tag = task_fragment_2 >>>>>>>>>
01-07 09:42:41.447  31645-31686/com... W/chromium? [WARNING:proxy_service.cc(890)] PAC support disabled because there is no system implementation
01-07 09:42:41.463  31645-31645/com... W/art? Attempt to remove local SIRT entry from IRT, ignoring
01-07 09:42:41.475  31645-31697/com... W/art? Thread[20,tid=31697,Native,Thread*=0x490354f0,peer=0x653769b0,"Thread-54681"] attached without supplying a name
01-07 09:42:41.494  31645-31645/com... W/System.err? onResume +++++++++++++++++++
01-07 09:42:41.652  31645-31645/com... W/System.err? *** onNavigationItemSelected -- where we need to go on kill-revival, to update list adapter ***
01-07 09:42:41.661  31645-31645/com... W/InputMethodManager? Ignoring onBind: cur seq=16279, given seq=16278
01-07 09:42:41.730  31645-31709/com... W/art? Thread[23,tid=31709,Native,Thread*=0x4b237a90,peer=0x653c5138,"Thread-54684"] attached without supplying a name
01-07 09:42:42.640  31645-31645/com... W/System.err? *** Post-Execute for data download & extraction ***
01-07 09:42:42.643  31645-31645/com... W/System.err? &&&&&&&&&&& DONE !!! and mTaskFragment is NULL
01-07 09:42:44.897  31645-31718/com... W/art? Thread[25,tid=31718,Native,Thread*=0x4cca44b0,peer=0x65579fb0,"Thread-54686"] attached without supplying a name

I appreciate your consideration of this mystery. I have left a few additional warnings in the logcat, in case someone wants to enlighten me about them. I'm still new at Android, and have not yet found all of the warnings in useful web searches.

Community
  • 1
  • 1
wwfloyd
  • 312
  • 3
  • 11

1 Answers1

0

It seems that nulling mTaskFragment is not enough to eliminate it. Using a fragment transaction to remove the fragment first, does the trick. So, finishTheRefresh() looks like this:

private void finishTheRefresh(boolean successful) {

    //if (mTaskFragment != null) mTaskFragment = null;

    if (mTaskFragment != null) {
        FragmentManager fm = getFragmentManager();
        fm.beginTransaction().remove(mTaskFragment).commit();
        mTaskFragment = null;
    }

    setRefreshActionButtonState(false);
    System.err.println("&&&&&&&&&&& DONE !!! and mTaskFragment is NULL");

    if (successful) refreshDisplayList();
}

I believe this also recovers more memory.

wwfloyd
  • 312
  • 3
  • 11