Android:从应用程序切换后保持片段(对于ActionBar选项卡)运行

时间:2012-08-26 00:18:19

标签: android android-fragments android-actionbar

我正在创建一个涉及多个片段的应用程序作为操作栏上的选项卡。当我切换选项卡关闭应用程序时,我需要保持这些片段的进程运行(不是结束应用程序,但是当按下主页或返回时我希望应用程序继续在后台运行)。因此,为了在切换选项卡时保持片段运行,我修改了sdk中的一个示例TabListener来显示和隐藏而不是附加和分离。代码是:

public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
    private Fragment mFragment;
    private final Activity mActivity;
    private final String mTag;
    private final Class<T> mClass;
    private final Bundle mArgs;


    public TabListener(Activity activity, String tag, Class<T> clz) {
        this(activity, tag, clz, null);
    }

    public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
        mActivity = activity;
        mTag = tag;
        mClass = clz;
        mArgs = args;

        // Check to see if we already have a fragment for this tab, probably
        // from a previously saved state.  If so, deactivate it, because our
        // initial state is that a tab isn't shown.
        mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
        if (mFragment != null && !mFragment.isHidden()) {
            FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
            ft.hide(mFragment);
            ft.commit();
        }
    }

    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        if (mFragment == null) {
            mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
            ft.add(android.R.id.content, mFragment, mTag);
        } else {
            ft.show(mFragment);
        }
    }

    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        if (mFragment != null) {
            ft.hide(mFragment);
        }
    }

    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        // User selected the already selected tab. Usually do nothing.
    }
}

标签的创建方式如下:

    ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    ActionBar.Tab aTab= actionBar.newTab().setText("Tab A").setTabListener(new TabListener<AFragment>(this, "AFrag", AFragment.class));
    actionBar.addTab(aTab);
    ActionBar.Tab bTab= actionBar.newTab().setText("Tab B").setTabListener(new TabListener<BFragment>(this, "BFrag", BFragment.class));
    actionBar.addTab(bTab);

所以这似乎有用,至少可以切换标签。有时片段会出现在彼此的顶部,虽然这是与TabListener的不同实现,并且从那以后它没有发生,所以它现在可能已经消失了。我不知道为什么会这样,所以我不知道如何复制它。

虽然关闭应用程序时非常错误。大多数情况下,当按下主页时,应用程序仍然可以运行并在我再次打开时运行。有时它不会,这很奇怪。按下也会关闭应用程序,但是再次启动它似乎从一开始就重新启动应用程序,这是不希望的。有时当从那里向后按时它将返回到先前运行的片段。

虽然它很随机且不稳定。它何时起作用是不可预测的。什么是最好的方法来提高稳定性,以便在它关闭时继续运行,重新打开应用程序不会重新启动它?

2 个答案:

答案 0 :(得分:0)

与活动一样,Fragments可以将其状态保存在Bundle中,当调用onCreate()时,它会被传入。你可以考虑保存状态,这样即使你的应用程序被杀死(对于内存)你也可以恢复它。

另外我建议使用

ft.addToBackStack(null)
    .remove(CurrentFragment)
    .add(ToShowFragment)
    .commit()

这样您就可以使用popBackStack()轻松处理添加和删除碎片。另请注意replace()无法弹出后台堆栈,因为它没有正确反转(您将获得状态异常)

答案 1 :(得分:0)

您可以尝试使用Fragment.setRetainInstance(true)来保留Fragment,虽然这可能仅适用于方向更改,但文档有点不清楚。

如果没有我知道的方法可以保留碎片。也许您最好的选择是将您想要保留的所有内容保存到Fragment.onSaveInstanceState(..)中的Bundle对象中,然后在Fragment.onCreate(..)Fragment.onCreateView(..)中读取此数据。

另一个我不太了解的替代方法是使用Fragment.SavedState类,它似乎与上面类似,只是你可以随时手动保存状态。这需要您进行相当多的编码,但会给您更大的控制权