为什么标记的任务片段在被清空后仍然存在?

Why does tagged task fragment live on after being nulled?

我正在使用一个无头的、保留的任务片段来下载和处理数据,因此 UI 线程不会被阻塞,并且可以优雅地处理配置更改。基本逻辑来自 here and here,但是,我进行了更改以允许使用 UI 片段,而不是 UI Activity.

有效。我唯一的问题是,在恢复时——在我的应用程序被系统杀死之后——任务片段在不应该运行的时候运行。对于这种类型的恢复,我已经从持久存储中恢复了数据,并且不想再次下载。但是请注意,任务片段的这种多余运行 只有在我之前单击刷新 时才会发生,从而创建了任务片段的首次使用。

这是我处理任务片段的地方:

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); 
    }
}

并且,从单击按钮开始:

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();
    }
}

来自任务片段的 onPostExecute() 回调调用这个:

private void finishTheRefresh(boolean successful) {

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

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

所以,现在到 logcat。这是 Kill 复兴,当 refresh taskfragment 以前没有运行时,它显示了所需的行为。请注意 onNavigationItemSelected() 是在 onResume() 中设置 actionBar 后由系统调用的。顺便说一句,从 SD 恢复数据发生在应用程序对象中:

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

这里我刷新一下:

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

还有,杀掉复活的问题,数据已经下载到哪里了。没有按钮点击,taskfragment onPostExecute() 回调已经运行。 当我之前已将 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

感谢您对这个谜团的考虑。我在 logcat 中留下了一些额外的警告,以防有人想启发我。我还是 Android 新手,还没有在有用的网络搜索中找到所有警告。

似乎nulling mTaskFragment 不足以消除它。首先使用片段事务删除片段,就可以了。所以,finishTheRefresh() 看起来像这样:

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();
}

我相信这也能恢复更多的内存。