当前位置: 首页 > 知识库问答 >
问题:

如何在两个片段之间切换,而不必每次重新创建片段?

史昱
2023-03-14

我正在开发一个android应用程序,它使用导航抽屉在两个片段之间切换。然而,每次我切换时,片段都会被完全重新创建。

这是我主要活动的代码。

/* The click listener for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        selectItem(position);
    }
}

private void selectItem(int position) {
    android.support.v4.app.Fragment fragment;
    String tag;
    android.support.v4.app.FragmentManager; fragmentManager = getSupportFragmentManager();

    switch(position) {
        case 0:
            if(fragmentManager.findFragmentByTag("one") != null) {
                fragment = fragmentManager.findFragmentByTag("one");
            } else {
                fragment = new OneFragment();
            }
            tag = "one";
            break;
        case 1:
            if(fragmentManager.findFragmentByTag("two") != null) {
                fragment = fragmentManager.findFragmentByTag("two");
            } else {
                fragment = new TwoFragment();
            }
            tag = "two";
            break;
    }

    fragment.setRetainInstance(true);
    fragmentManager.beginTransaction().replace(R.id.container, fragment, tag).commit();

    // update selected item and title, then close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mNavTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

我设置了一些调试日志记录,每次调用selectItem时,都会销毁一个片段,而创建另一个片段。

有什么方法可以防止碎片被重新创建,而只是重复使用它们吗?

共有3个答案

和柏
2023-03-14

替换方法会销毁您的片段。一种解决方法是将它们设置为可见性。GONE,另一种(不太容易的)方法是将它们保存在变量中。如果您这样做,请确保您不会左右泄漏内存。

澹台冯浩
2023-03-14

使用带有标签的附加/分离方法:

分离将破坏视图hirachy,但保持状态,就像在后台一样;这将使“不可见”片段具有更小的内存占用。但请注意,您需要正确实现片段生命周期(您首先应该这样做)

从UI分离给定片段。这与将其放在后堆栈上时的状态相同:片段从UI中删除,但其状态仍由片段管理器主动管理。进入此状态时,其视图层次结构将被破坏。

第一次添加片段时

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.add(android.R.id.content, new MyFragment(),MyFragment.class.getSimpleName());
t.commit();

然后拆下它

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.detach(MyFragment.class.getSimpleName());
t.commit();

并再次连接,如果切换回,状态将保持不变

FragmentTransaction t = getSupportFragmentManager().beginTransaction();
t.attach(getSupportFragmentManager().findFragmentByTag(MyFragment.class.getSimpleName()));
t.commit();

但是你总是要检查片段是否已经添加,如果没有,则添加它,否则只需附加它:

if (getSupportFragmentManager().findFragmentByTag(MyFragment.class.getSimpleName()) == null) {
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.add(android.R.id.content, new MyFragment(), MyFragment.class.getSimpleName());
    t.commit();
} else {
    FragmentTransaction t = getSupportFragmentManager().beginTransaction();
    t.attach(getSupportFragmentManager().findFragmentByTag(MyFragment.class.getSimpleName()));
    t.commit();
}
虞博涛
2023-03-14

在@meredrica指出replace()会破坏片段之后,我又回顾了FragmentManager文档。这就是我想出的解决方案,似乎奏效了。

/* The click listener for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        selectItem(position);
    }
}

private void selectItem(int position) {
    android.support.v4.app.FragmentManager; fragmentManager = getSupportFragmentManager();

    switch(position) {
        case 0:
            if(fragmentManager.findFragmentByTag("one") != null) {
                //if the fragment exists, show it.
                fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("one")).commit();
            } else {
                //if the fragment does not exist, add it to fragment manager.
                fragmentManager.beginTransaction().add(R.id.container, new OneFragment(), "one").commit();
            }
            if(fragmentManager.findFragmentByTag("two") != null){
                //if the other fragment is visible, hide it.
                fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("two")).commit();
            }
            break;
        case 1:
            if(fragmentManager.findFragmentByTag("two") != null) {
                //if the fragment exists, show it.
                fragmentManager.beginTransaction().show(fragmentManager.findFragmentByTag("two")).commit();
            } else {
                //if the fragment does not exist, add it to fragment manager.
                fragmentManager.beginTransaction().add(R.id.container, new TwoFragment(), "two").commit();
            }
            if(fragmentManager.findFragmentByTag("one") != null){
                //if the other fragment is visible, hide it.
                fragmentManager.beginTransaction().hide(fragmentManager.findFragmentByTag("one")).commit();
            }
            break;
    }

    // update selected item and title, then close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mNavTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

我也添加了这一点,但我不确定这是否必要。

@Override
public void onDestroy() {
    super.onDestroy();
    FragmentManager fragmentManager = getSupportFragmentManager();
    if(fragmentManager.findFragmentByTag("one") != null){
        fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("one")).commit();
    }
    if(fragmentManager.findFragmentByTag("two") != null){
        fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("two")).commit();
    }
}
 类似资料:
  • 当使用底部导航视图在片段之间切换时,每次按下按钮时都会重新创建片段。 这是我的代码:

  • 我有一个带有底栏的main_activity。我正在使用这个底栏在片段之间导航。然而,有一个片段不能通过底部栏直接导航。它必须通过MapView和从片段中访问。然而,每当我使用InfoWindow时,该应用程序就会崩溃。这是我的代码 异常:main process:com.teslaqubitsins.fasih.teslahcm,pid:2573 java.lang.nullpointerexc

  • 我尝试在片段子类中使用onSaveInstanceState(Bundle outState)方法保存数据。 解释:我创建了一个类FragmentA,它扩展了这个类中的Fragment。我有一个变量名count,当我单击按钮时,count的值发生了变化(最初count=0)。我想保存count的值,即使方向发生了变化(纵向到横向,反之亦然)。我的MainActivity类动态加载片段。 我的代码:

  • 我正在进行一项活动,其中有TabLayout和两个表示选项卡内容的片段。我在活动的OnCreate方法中手动管理打开选项卡的当前状态: 这只是一个简单的例子。我真正的代码是用C语言编写的,并且有一些其他逻辑来存储和管理活动重启之间的状态。 配置更改时的问题(例如开关方向): 打开的碎片被摧毁 活动被破坏 活动重启 在onCreate方法中,当调用super.onCreate(savedInstan

  • 我在android中使用BottomNavigationView来制作一个像Instagram一样的应用程序。我在NavigationTabs中使用片段。应用程序有5个标签初始我已经设置为活动标签的中间标签和加载它一旦应用程序启动。当我单击任何其他选项卡时,就会进行网络调用并加载数据。现在,当我按下on back按钮或再次单击last选项卡(在启动时加载)时,片段将被重新创建,并进行网络调用以加载