【问题标题】:Tabbed fragments list views are not updated when related data is changed in other fragment当其他片段中的相关数据发生更改时,选项卡式片段列表视图不会更新
【发布时间】:2016-03-18 13:25:46
【问题描述】:

我在我的应用程序中使用 TabLayout 作为选项卡式视图。我添加了三个列表片段 - 每个选项卡一个。

当从任何片段中添加/删除新记录时,应该更改任何片段的内容(并且必须更新列表视图)。

但是在我修改了一些数据并滑动到下一个选项卡后,列表视图没有更新并保留了旧数据。

我创建了一个在所有 ListFragments 中实现的接口,如下所示:

public interface UpdatableFragment {

    void updateContent();
}

public class LogFragment implements  UpdatableFragment{
...
    @Override
    public void updateContent() {

        Activity activity = getActivity();

        if (isAdded() && activity != null) {

            getLoaderManager().restartLoader(LOG_LIST_LOADER, null, this);
        }
    }
...
}

我在 MainActivity 选项卡中调用方法选择监听器

 tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

                if(adapter != null){

                    int position = viewPager.getCurrentItem();

                    viewPager = (ViewPager) findViewById(R.id.viewpager);
                    viewPager.setCurrentItem(position);

                    Fragment tabbedFragment =  adapter.getItem(viewPager.getCurrentItem());

                    if(tabbedFragment instanceof UpdatableFragment){

                        ((UpdatableFragment) tabbedFragment).updateContent();                               
                    }
                }
            }

但 updateContent() 方法中的条件 if (isAdded() && activity != null) 有时会返回 false,因为活动变为空。在其他时候,它返回 MainActivity 实例并且加载器重新启动。

为什么会发生这种不一致的行为?如何让 ListFragments 在选择其对应的选项卡时始终显示新鲜内容?

编辑 添加片段寻呼机代码

class ViewPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {

        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

【问题讨论】:

    标签: android listview android-fragments tabs


    【解决方案1】:

    getItem(int position) 方法不会返回对当前位于 ViewPager 的该位置的 Fragment 的引用。 getItem() 方法在PagerAdapter 中使用,当它调用instantiateItem() 来创建你的视图/片段时,所以当你调用getItem(int position) 它为你创建一个全新的Fragment,这不是添加/附加的到您的 Activity (导致您的 if 检查中的 false/null )。如果您查看FragmentPagerAdapter.instantiateItem() 的代码,您可以看到它在哪里调用getItem(),然后添加FragmentFragmentManager

    解决此问题的一种方法是将Fragment 引用缓存在FragmentPagerAdapter 中(通过缓存instantiateItem() 返回的Fragment 并删除adapter.destroyItem() 中的引用),或调用@987654339 @ 使用更新的数据重新创建您的视图。

    更新:

    您想在您的FragmentPagerAdapter 中添加类似的内容:

    public class Adapter extends FragmentPagerAdapter {
    
      private SparseArray<Fragment> fragmentCache = new SparseArray<>();
    
      @Override public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        fragmentCache.put(position, fragment);
        return fragment;
      }
    
      @Override public void destroyItem(ViewGroup container, int position, Object object) {
        fragmentCache.remove(position);
        super.destroyItem(container, position, object);
      }
      // other code....
    }
    

    然后您可以从fragmentCache 获取对当前适配器中所有片段的引用,然后您可以在它们上调用您的updateContent 方法。

    【讨论】:

    • 谢谢 Alex,我更新了我的问题以添加 pagerAdapter 部分。请评论我使用的实际代码。
    • 我想我在addFragment() 中创建片段时缓存了它们(在 myFragmentList 中),并使用“缓存”从中获取片段项。在缓存原始片段方面,SparseArray 实现有什么不同?
    • Alex,行为也不一致。有时它会起作用。只有在某些情况下它无法工作。如果总是返回片段的新实例,那么它不适用于某些标签滑动。
    • Alex,还有一件事:我将 getItem(int position) 返回的片段对象 ID 与适配器中存在的原始片段实例的 ID 进行了比较。他们是一样的。所以我实际上是在调用原始片段的方法。
    • 在什么情况下会出现不一致?滚动浏览ViewPager 时?选择Tab?屏幕旋转?等等。我使用您提供的代码制作了一个小型测试项目,并在测试片段中更新了TextView,在我看来没有任何问题。
    猜你喜欢
    • 2017-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 1970-01-01
    相关资源
    最近更新 更多