Android 当其他片段中的相关数据发生更改时,选项卡式片段列表视图不会更新

Android 当其他片段中的相关数据发生更改时,选项卡式片段列表视图不会更新,android,listview,android-fragments,tabs,Android,Listview,Android Fragments,Tabs,我在我的应用程序中使用了选项卡式视图的表格布局。我添加了三个列表片段——每个选项卡一个 当从任何片段中添加/删除新记录时,应该更改其中任一片段的内容(并且必须更新列表视图) 但在我修改一些数据并滑动到下一个选项卡后,列表视图不会更新并保留旧数据 我创建了一个在所有ListFragments中实现的接口,如下所示: public interface UpdatableFragment { void updateContent(); } public class LogFragment

我在我的应用程序中使用了选项卡式视图的表格布局。我添加了三个列表片段——每个选项卡一个

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

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

我创建了一个在所有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选项卡SelectListener中调用该方法

 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,因为活动变为null。在其他时间,它返回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);
    }
}
class ViewPagerAdapter扩展了FragmentPagerAdapter{
私有最终列表MFFragmentList=new ArrayList();
私有最终列表MFFragmentTitleList=new ArrayList();
公共视图页面编辑器(碎片管理器){
高级经理;
}
@凌驾
公共片段getItem(int位置){
返回MFFragmentList.get(位置);
}
@凌驾
public int getCount(){
返回MFFragmentList.size();
}
public void addFragment(片段片段,字符串标题){
添加(片段);
MFFragmentTitleList.add(标题);
}
@凌驾
公共字符序列getPageTitle(int位置){
返回MFFragmentTitleList.get(位置);
}
}
方法
getItem(int位置)
不会返回对当前位于
ViewPager
位置的
片段的引用。
getItem()
方法在调用
instantiateItem()
创建视图/片段时,在
PagerAdapter
中使用,因此当您调用
getItem(int position)
时,它会为您创建一个全新的
Fragment
,而这不会添加/附加到
活动中
(导致if检查中出现false/null)。如果查看
FragmentPagerAdapter.InstanceItem()
的代码,可以看到它在哪里调用
getItem()
,然后使用
FragmentManager
添加
片段

解决此问题的一种方法是在
FragmentPagerAdapter
中缓存
片段
引用(通过缓存
实例化Item()
返回的
片段
并删除
适配器.destroyItem()
中的引用,或者调用
适配器.notifyDataSetChanged()来实现此目的)
使用更新的数据重新创建视图

更新:

您想在
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....
}
公共类适配器扩展FragmentPagerAdapter{
私有SparseArray fragmentCache=新SparseArray();
@重写公共对象实例化项(视图组容器,int位置){
Fragment Fragment=(Fragment)super.instanceItem(容器,位置);
fragmentCache.put(位置,片段);
返回片段;
}
@替代公共项(视图组容器、int位置、对象){
碎片缓存。删除(位置);
超级项目(容器、位置、对象);
}
//其他代码。。。。
}

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

谢谢Alex,我更新了我的问题以添加pagerAdapter部分。请评论我使用的实际代码。我想我已经缓存了它们(在我的FragmentList中)在
addFragment()中创建片段时
并使用“缓存”从中获取片段项。SparseArray实现在缓存原始片段方面有什么不同?Alex,而且行为不一致。有时它可以工作。只有在某些情况下它无法工作。如果总是返回片段的新实例,那么它就无法工作Alex,还有一件事:我比较了从getItem(int位置)返回的片段对象ID与适配器中存在的原始片段实例的不一致。它们是相同的。因此我实际上调用了原始片段的方法。在什么情况下会发生不一致?当滚动浏览
ViewPager
时?当选择
选项卡
?屏幕旋转?等时。我使用g您提供的代码并在测试片段中更新了
TextView
,在我看来没有任何问题。