【问题标题】:Removing a fragment and then re-adding it删除片段然后重新添加它
【发布时间】:2016-03-01 18:00:00
【问题描述】:

我在我的活动中编写了一个方法setLoading,它负责设置我的应用程序的“加载”状态。此方法负责实例化LoadingFragment,删除它的任何现有实例(使用FragmentManager),然后根据它的第一个参数loading,将其添加到两个可能的容器之一(取决于top 参数)。

protected LoadingFragment loadingFragment;

public void setLoading(boolean loading, boolean top) {
    FragmentManager fragmentManager = getFragmentManager();

    // Create LoadingFragment instance if it has not already been created
    if (loadingFragment == null || !(loadingFragment instanceof LoadingFragment)) {
        loadingFragment = new LoadingFragment();
    }

    // Remove the fragment first if it is present
    fragmentManager
            .beginTransaction()
            .remove(loadingFragment)
            .commit();

    // Only if loading is true should we display the fragment
    if (loading) {
        // Decide which container we're going to put the fragment in
        int id = top ? R.id.topContainer : R.id.container;

        // Place the fragment in the right position
        fragmentManager
                .beginTransaction()
                .add(id, loadingFragment)
                .commit();
    }
}

public void setLoading(boolean loading) {
    setLoading(loading, true);
}

我在活动的其他地方触发了setLoading(true),我在测试时注释掉了它对应的setLoading(false)

我希望每次调用setLoading(true) 时都会出现我的LoadingFragment。第一次调用不应删除任何内容,因为此时它不存在。所有后续调用都应删除现有的LoadingFragment 并重新添加。

发生的情况是,第一次调用 setLoading(true) 确实创建了 LoadingFragment 并将其放入正确的容器中。但是,随后对setLoading(true) 的调用会删除该片段,但似乎从未重新添加它。我检查了该片段确实存在,并且在添加时它的类型为LoadingFragment,我还检查了它是否正在调用onCreateView 方法。

我做错了吗?

编辑

使用下面 H Raval 给出的答案作为基础,我现在想出了以下内容:

public void setLoading(boolean loading, boolean top) {
    FragmentManager fragmentManager = getFragmentManager();

    Fragment currentLoadingFragment = fragmentManager.findFragmentById(R.id.loadingFragment);
    if (currentLoadingFragment != null) {
        fragmentManager
                .beginTransaction()
                .remove(currentLoadingFragment)
                .commit();
    }

    if (loading) {
        int id = top ? R.id.topContainer : R.id.container;

        fragmentManager
                .beginTransaction()
                .add(id, new LoadingFragment())
                .commit();
    }
}

这似乎按预期工作。似乎主要区别在于这段代码每次都创建一个新的LoadingFragment 实例(当loading = true 时),而最初我试图使用相同的实例并只是使用FragmentManager 添加/删除它。

出于兴趣,我在使用remove 后是否需要创建一个新实例?这是正确的方法吗?还是在使用同一个实例时它仍然可以工作?另外,如果建议每次都创建一个新实例,在清理、释放资源等方面我应该做些什么(也许有一种方法可以优雅地销毁过时的实例)?

【问题讨论】:

  • 而不是使用片段管理器用户替换的add方法
  • 我会这样做,但是,在调用该方法之前我不知道片段是否已经存在。不仅如此,我的第二个参数允许我将片段放入不同的容器中,如int id = top ? R.id.topContainer : R.id.container; 行所述。因此,我不认为replace 会是要走的路
  • 用替换你可以设置片段的标签......并且在添加时你可以测试标签片段是否存在......检查这个stackoverflow.com/questions/9294603/…
  • 您也可以使用add 方法设置标签。你说得对,我可以检查它是否存在,我也可以使用fragmentManager.findFragmentById() 来做到这一点。但是,我认为这不能解决我的问题。我的问题是当我重新添加片段时它不可见。我很乐意使用replace 方法,但如前所述,我并不总是希望将片段放在同一个容器中(我的第二个参数允许替代)
  • 当然,如果你知道一种方法可以达到我想要的结果,通过使用替换,无论如何发布一个答案,如果它有效,我会接受。

标签: android android-layout android-fragments


【解决方案1】:

我已经对您的代码进行了一些更改,并且非常适合我..如果您遇到任何困难,请告诉我

public void loadFragment(boolean loading, boolean top){
        FragmentManager fragmentManager = getSupportFragmentManager();

          loadingFragment = new LoadingFragment();

        // Only if loading is true should we display the fragment
        if (loading) {
            // Decide which container we're going to put the fragment in
            int id = top ? R.id.topContainer : R.id.container;

            if(top){
                if(fragmentManager.findFragmentByTag("loadingFragment")!=null)
                    fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("loadingFragment")).commit();

                fragmentManager
                        .beginTransaction()
                        .replace(R.id.topContainer, loadingFragment,"toploadingFragment")
                        .commit();
            }else{
                if(fragmentManager.findFragmentByTag("toploadingFragment")!=null)
                    fragmentManager.beginTransaction().remove(fragmentManager.findFragmentByTag("toploadingFragment")).commit();

                fragmentManager
                        .beginTransaction()
                        .replace(R.id.container, loadingFragment,"loadingFragment")
                        .commit();
            }

        }

【讨论】:

  • 感谢您的回答。你的在某种程度上确实有效(尽管loading = false 时它不会删除片段)。使用您的代码作为基础,我自己周围一团糟,我发现导致它起作用的主要区别是您每次都在创建一个新的 LoadingFragment 实例,而我试图使用相同的实例.我的代码使用findFragmentById 而不是findFragmentByTag,它使用add/remove 而不是replace。一切仍然按预期工作。有关详细信息,请参阅我的编辑。
  • 您必须每次都创建新实例,因为如果您使用相同的实例,则无法附加具有不同 id 的相同片段...它将引发异常...检查此stackoverflow.com/questions/9906254/…跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
  • 2015-12-05
相关资源
最近更新 更多