【问题标题】:Fragment in ViewPager loses its viewViewPager 中的 Fragment 失去了它的视图
【发布时间】:2016-03-02 19:35:34
【问题描述】:

我使用 Android Studio 的选项卡式活动开始了一个新项目。它使用 ViewPager 和 3 个片段 = fragment1、fragment2 和 fragment3 创建了一个活动。 我将fragment1 更改为有一个listView 和一个TextView,我在创建片段时对其进行初始化。 listView 中的数据是从 SQL 数据库中读取的。 应用程序启动时,会显示 fragment1,listView 显示从 SQL 读取的数据。 当我从 fragment1 滑动到 fragment2 并返回时,fragment1 正确显示列表视图。但是,当我滑动到 fragment3 并返回到 fragment1 时,listview 数据丢失并且我得到一个空白屏幕,尽管 textview 显示正确。 当我将应用程序更改为只有 2 个片段时,它不会发生,我可以从片段 1 滑动到片段 2 并多次返回,而不会丢失任何数据。在我添加第三个片段的那一刻,数据在第一次滑动到片段 3 时丢失,但如果我只在片段 1 和片段 2 之间滑动,数据不会丢失。 知道为什么会这样吗?

【问题讨论】:

  • 如果没有可重现的例子,就不可能准确地说明为什么会发生这种情况。两个 Fragment 不会出现问题的原因是 FragmentPagerAdapter 使两个 Fragment 保持活动状态,请参见此处:stackoverflow.com/questions/8348707/… 和此处:stackoverflow.com/questions/10853611/…
  • 项目太大,无法发布。如果我们很快找不到解决方案,我会创建一个小版本来发布。
  • 项目太大,无法发布。如果我们很快找不到解决方案,我将创建一个小版本来发布。无论如何,我进一步测试并发现发生的情况是列表视图丢失了它的适配器(listView.getAdapter() 返回 null)。因此,在重新显示页面之前,我现在测试这种情况,如果存在,我重新创建适配器,并且列表正确显示。这能给你一个提示吗?
  • 问题我已经解决了。

标签: android listview android-fragments


【解决方案1】:

这是因为默认情况下ViewPager 有一个名为setOffscreenPageLimit(int i) 的函数。这告诉ViewPager 有多少Fragments 需要存储在内存中。默认为“2”。因此,当您从 Fragment 1 滑动到 Fragment 2 时,它仍会将 Fragment 1 保留在内存中,并且不会从内存中销毁它。但是当您滑动到 Fragment 3 时,它会在内存中有 Fragment 2Fragment 3,因此它会删除 Fragment 1.

这就是为什么当您返回第一个 Fragment 时,它会丢失视图或数据。

尝试使用

mViewPager.setOffscreenPageLimit(your total fragment count +1);

或者更好的解决方案 刷入ViewPager 时不要replace 您的片段。 Push 它到后台堆栈,当你回到它时,检查后台堆栈,如果片段在那里,那么只需 Pop 它并显示它。

代码如下:

public void pushFragments(String tag, Fragment fragment) {
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    if (manager.findFragmentByTag(tag) == null) {
        ft.add(R.id.frame_container, fragment, tag);
    }
    String tagOne="com........Frag_one"; //your fragment class name
    String tagTwo="com........Frag_two";
    String tagThree="com........Frag_three";
    String tagFour="com........Frag_profile";

    Fragment fragmentOne = manager.findFragmentByTag(tagOne);
    Fragment fragmentTwo = manager.findFragmentByTag(tagTwo);
    Fragment fragmentThree = manager.findFragmentByTag(tagThree);
    Fragment fragmentFour = manager.findFragmentByTag(tagFour);
    manager.executePendingTransactions();
    // Hide all Fragment
    if (fragmentOne != null) {
        ft.hide(fragmentOne);
    }
    if (fragmentTwo != null) {
        ft.hide(fragmentTwo);
    }
    if (fragmentThree != null) {
        ft.hide(fragmentThree);
    }
    if (fragmentFour != null) {
        ft.hide(fragmentFour);
    }
    // Show  current Fragment
    if (tag.equals(tagOne)) {
        if (fragmentOne != null) {
            ft.show(fragmentOne);
        }
    }
    if (tag.equals(tagTwo)) {
        if (fragmentTwo != null) {
            ft.show(fragmentTwo);
        }
    }
    if (tag.equals(tagThree)) {
        if (fragmentThree != null) {
            ft.show(fragmentThree);
        }
    }
    if (tag.equals(tagFour)) {
        if (fragmentFour != null) {
            ft.show(fragmentFour);
        }
    }
    ft.commit();
}

你是这样称呼它的:

Fragment fragment = new Frag_one();
pushFragments(fragment.getClass().getName(),fragment);

【讨论】:

    【解决方案2】:

    问题已解决。正如@Daniel Nugent 所指出的,问题是由于适配器在内存中保留了 3 个片段。页面中的数据是从数据库加载的,因此当重新创建视图时,当用户滑动时破坏和重新创建片段时,listview 适配器已经丢失了数据,并且必须重新填充它。该问题不会出现在简单的示例中,因为通常呈现的数据是静态的,并且是在 onCreateView 方法中加载的。

    【讨论】:

      猜你喜欢
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-31
      • 2012-06-16
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多