【问题标题】:Android ViewPager + Fragments with dynamic ListViewsAndroid ViewPager + 带有动态 ListViews 的片段
【发布时间】:2015-02-12 23:19:45
【问题描述】:

在我的应用中,我有标签活动(比如说 10 个标签)。每个标签页都包含FragmentListView(此ListView 中显示的数据是从我的服务器动态加载的)。我使用ViewPager来显示这些页面。我不想将所有Fragments 都保留在内存中,所以我决定使用FragmentStatePagerAdapter(我的适配器类扩展了这些类)。

  1. 假设选择了第三个选项卡。然后,例如,当我转到第一个选项卡时,应该从头开始创建此选项卡的 Fragment(这很好,这就是 FragmentStatePagerAdapter 的工作方式)但 无需 恢复此片段的先前状态(例如,ListView 不应滚动到上次访问此 Fragment 时保存的位置 - 现在已滚动)。 所以我的第一个问题是:我怎样才能实现这样的行为?换句话说,我希望我的适配器在从头开始创建时不要恢复Fragmentstate。

  2. 再一次,假设选择了第三个选项卡。然后,例如,当我转到第二个选项卡时,Fragmentfor 这个选项卡应该仍在内存中(这很好,这就是 FragmentStatePagerAdapter 的工作方式),但在这种情况下,我想决定我的 ListViewdata 是否应该更新(取决于某些条件)。如何通知Fragment 它已被选中?

【问题讨论】:

    标签: android android-fragments android-listview android-viewpager fragmentstatepageradapter


    【解决方案1】:

    对于 #1,请查看 this 博客文章。他们谈论修复 FragmentStatePagerAdpater 以处理索引的片段类发生变化的情况,这并不是您想要的。但是,它详细显示了状态是如何保存/恢复的,您应该能够从那里弄清楚如何防止它。

    对于#2,在包含 ViewPager 的 Fragment 中实现 OnPageChangeListener。然后使用this 在当前片段发生变化时获取它,以便您可以在其上调用一些公共方法,告诉它更新。

    【讨论】:

    • 在您发布答案之前,这正是我所做的。我使用FragmentStatePagerAdapter 代码实现了我自己的PagerAdapter,没有状态保存/恢复部分。它对我的第二个问题也很有用,因为现在,在我自己的适配器中,我可以轻松访问当前的Fragment(因为有内部Fragments 列表 - 不需要额外的映射/数组)。我只是害怕我的想法是正确的,但你的答案完全一样,所以我现在确定。非常感谢。
    【解决方案2】:

    我希望我的适配器在创建时不要恢复 Fragmentstate 从头开始。

    将以下代码添加到FragmentStatePagerAdapter

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }
    

    如何通知此 Fragment 它已被选中?

    当您在fragmentStatePagerAdaptergetItem 中加载每个fragment 时,还使用getInstance(链接的示例很好)设计模式将位置传递给片段。在onPageSelected(int position) 中调用LocalBroadcastManager 并将位置作为额外的。在每个片段中检查意图,如果额外中的位置与片段中存储的位置相同,这意味着用户选择了该片段,因此在onReceive 方法中更新列表。

    【讨论】:

    • 1.我已经测试了您的解决方案,但它不起作用,我已经检查了原因。根据 ViewPager 源代码,当调用 mAdaper.getItemPosition(someObject) 后,它返回 POSITION_NONEFragment 因为此页面被销毁(适配器在销毁之前保存Fragment 状态),但它仍然不能阻止FragmentStatePagerAdapter重新创建时恢复Fragments 状态。更重要的是,它似乎效率低下,因为每次调用 notifyDataSetChanged() 时,所有 Fragments 都会被销毁并重新创建。 2. 没关系,但我选择了更简单的解决方案。
    【解决方案3】:

    对于#1,AFAIK,当转到第一个选项卡时,与该选项卡的 Fragment 相关联将再次创建,就像您使用 FragmentStatePagerAdapter 时它永远不会访问一样。现在你说 ListView 是滚动的,你确定你使用的是 FragmentStatePagerAdapter??

    另一方面,如果您使用FragmentPagerAdapter,它将从 FragmentManager 中分离所有关闭的 Fragment,但将它们保留在内存中,这就是为什么当您直接从第三个选项卡返回到第一个选项卡时,您会看到 ListView 停留最后状态。你提到的行为让我觉得你似乎在使用 FragmentPagerAdapter 而不是 FragmentStatePagerAdapter。

    如果你确认是FragmentStatePagerAdapter,我相信如果你不手动恢复状态(即使用Fragment中的onSaveInstanceState()方法),回来的Fragment肯定会恢复到刚出生的样子。

    对于#2,如果您想在 Fragment 完全可见时执行某些操作,您可以覆盖 setUserVisibleHint 方法以将您的代码放在那里。

    public class YourFragement extend android.support.v4.app.Fragment {
        ...
        @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (conditions satisfied) {
                // do your job
            }
        }
        ...
    }
    

    【讨论】:

    • FragmentPagerAdapterFragmentStatePagerAdapter 具有相同的可见语义——唯一的区别是前者保留了Fragment 对象本身,而后者只保留了它们的状态。分离和销毁 Fragment 都会导致其 Views 被销毁,重新附加 Fragment 与创建具有相同保存状态的新 Fragment 具有相同的语义。
    • @corsair992 是的,你说得对,我很注意源代码终于找到FragmentManager破坏Fragment的地方,PagerAdater没有参与这个机制。感谢您的提醒,并为我的错误向大家道歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多