【问题标题】:How do I restore a previously displayed Fragment?如何恢复以前显示的 Fragment?
【发布时间】:2013-09-17 20:35:30
【问题描述】:

我在我的项目中使用了兼容包 v4,但在将 Fragment 从视图中移除后,我遇到了保留它的问题。我有我的Activity 显示 2 个片段......左侧的菜单框架,右侧的内容窗格。菜单框架有 3 个不同的菜单(片段)可以显示。

这就是我替换菜单片段的方式:

public void showMenuFragment( Fragment fragment, String tag ) {

        showFragment( R.id.menu_frame, fragment, tag, false);
        setLastMenuPushed( tag );
    }

protected void showFragment( int resId, Fragment fragment, String tag, boolean addToBackStack ) {

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();

        if ( fragmentManager.findFragmentByTag( tag ) != null && fragment.isAdded() ) {
            transaction.remove( fragment );
        }

        transaction.replace( resId, fragment, tag ).setTransition( FragmentTransaction.TRANSIT_FRAGMENT_OPEN ).setBreadCrumbShortTitle( tag );

        if ( addToBackStack ) {
            transaction.addToBackStack( tag );
        }

        transaction.commit();
    }

菜单Fragments 需要先加载数据才能显示,所以我展示了一个加载微调器。第一次加载后,我不想再次加载它,除非 Activity 完成。

当我调用showMenuFragment(...) 时,我尝试使用FragmentManager.findFragmentByTag(String tag) 传递Fragment,但它始终是null,所以每次我想显示不同的菜单时我都必须创建一个新的Fragment

我的问题是,这些Fragments 在被其他菜单替换后如何保留?我想避免保留对 Fragments 的手动引用,因为当设备旋转时,我的 Activity 类的实例被破坏,我会丢失这些引用。

编辑:用更简单的术语来说,我希望FragmentManager 跟踪以前的Fragments,而不必将它们添加到后台堆栈中。我不想点击返回按钮并看到显示的上一个菜单。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    刚刚想通了。当我添加新片段时,我没有删除片段,而是隐藏它们,然后在我想再次显示它们时显示它们。这是我修改后的方法:

    public void showMenuFragment( Fragment fragment, String tag, boolean addToBackStack ) {
    
            showFragment( R.id.menu_frame, fragment, tag, getLastMenuPushed(), addToBackStack );
            setLastMenuPushed( tag );
    }
    
    protected void showFragment( int resId, Fragment fragment, String tag, String lastTag, boolean addToBackStack ) {
    
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
    
            if ( lastTag != null ) {
                Fragment lastFragment = fragmentManager.findFragmentByTag( lastTag );
                if ( lastFragment != null ) {
                    transaction.hide( lastFragment );
                }
            }
    
            if ( fragment.isAdded() ) {
                transaction.show( fragment );
            }
            else {
                transaction.add( resId, fragment, tag ).setBreadCrumbShortTitle( tag );
            }
    
            if ( addToBackStack ) {
                transaction.addToBackStack( tag );
            }
    
            transaction.commit();
    }
    

    【讨论】:

    • 回想起来,我认为更好的解决方案是从 Activity 中“分离” Fragment 并在类中保留对它的硬引用。
    • 分离与隐藏的优势是什么?破坏视图会产生真正的影响吗?你有什么好的方法可以在不重新加载整个片段的情况下恢复它?
    • @ben Detach 将从屏幕上移除视图层次结构,这是一种更环保的方法。大多数视图在从 Fragment 中删除时都可以很好地保存它们的实例状态,因此在重新附加时我不会看到有什么大不了的。
    • 附加分离调用需要 api 级别 13 有没有其他方法。
    • 实际上,“detach() the old - add() the new”的作用与 replace() 相同,即使用 null 实例状态 Bundle 重新启动 Fragment 的生命周期,这样就不会t 帮助。
    【解决方案2】:

    我不确定这是否可能。 FragmentManager 只关心他的 BackStack 上的 Fragments。但是,如果您让FragmentActivity 实现onBackButtonPressed 并让自定义行为发生,您可以解决后退按钮按下的问题。您可以将它们委托给您的Fragments,或者根据您的应用逻辑显示另一个Fragment

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-20
      • 2021-10-07
      • 1970-01-01
      • 2016-03-21
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      相关资源
      最近更新 更多