FragmentPagerAdapter notifyDataSetChanged不起作用

45

我有一个FragmentPagerAdapter。它的getItem方法可以根据外部数据返回一个片段。当我更新要显示的数据后,我调用notifyDataSetChanged,但仍然没有任何反应。我确实重写了getItemPosition方法,返回POSITION_NONE:

public static class TabsAdapter extends FragmentPagerAdapter implements TabHost.OnTabChangeListener,
        ViewPager.OnPageChangeListener
{
    private final Context mContext;
    private final TabHost mTabHost;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    private PagerTabsFragments fragmentDisplayInfo = null; // for now only a
                                                            // single size
                                                            // back
                                                            // stack

    static class PagerTabsFragments
    {
        public int tabPosition;
        public Fragment fragmentToDisplay;
        public Object fragmentInfo;

        public PagerTabsFragments(int tab, Fragment frag, Object info)
        {
            tabPosition = tab;
            fragmentToDisplay = frag;
            fragmentInfo = info;
        }
    }

    public void SetFragmentToDisplay(int tabPosition, Fragment frag, Object info)
    {
        fragmentDisplayInfo = new PagerTabsFragments(tabPosition, frag, info);
        notifyDataSetChanged();
    }

    public void CancelFragmentToDisplay()
    {
        fragmentDisplayInfo = null;
    }
...
@Override
    public Fragment getItem(final int position)
    {
        if ((fragmentDisplayInfo != null) && (fragmentDisplayInfo.tabPosition == position))
        {
            return fragmentDisplayInfo.fragmentToDisplay;
        }
        final TabInfo info = mTabs.get(position);
        return Fragment.instantiate(mContext, info.clss.getName(), info.args);
    }

    @Override
    public int getItemPosition(Object item)
    {
        if (fragmentDisplayInfo == null)
        {
            return super.getItemPosition(item);
        }
        return POSITION_NONE;
    }
...

而外部更新是在一个点击事件中设置fragmentDisplayInfo变量。我进行了调试并看到fragmentDisplayInfo确实已经被初始化,getItemPosition方法确实返回POSITION_NONE,但getItem方法甚至没有被调用。这是为什么呢?

编辑:

如果您还没有这样做,请注意适配器的重写部分:

 @Override
public int getItemPosition(Object item)
{
    return POSITION_NONE;
}

你最终找到解决方案了吗? - AndroidEnthusiast
6个回答

79

Nik Myers所说的是正确的。但是还有一点遗漏。当调用notifyDataSetChanged方法时,会调用getItemPosition方法。您需要重写此方法才能重新加载片段。

 @Override
    public int getItemPosition(Object object) {
        // Causes adapter to reload all Fragments when
        // notifyDataSetChanged is called
        return POSITION_NONE;
    }

58

我不确定这一点,但你可以尝试使用FragmentStatePagerAdapter代替FragmentPagerAdapter。事实上,我也遇到了这个问题,这个方法帮助了我。


1
正如Skywalker所说,覆盖getItemPosition方法并返回POSITION_NONE值,https://dev59.com/3F0a5IYBdhLWcg3wqKKq#36348078 - Ahmad Vatani

5

在我上一个项目中,我也遇到了类似的问题。因此我找到了几个解决方案。

  1. by overriding getItemPosition in the pager adaptor but this is not a good idea.

    @Override
    public int getItemPosition(Object object) {
        // it will recreate all Fragments when
        // notifyDataSetChanged is called
        return POSITION_NONE;
    }
    
  2. The second one is cabezas Solution.

  3. Most Stable solution override getItemPosition in below fashion:

        @Override
        public int getItemPosition(Object object) {
            if (object instanceof MyFragment) {
                // Create a new method notifyUpdate() in your fragment 
                // it will get call when you invoke 
                // notifyDatasetChaged();
                ((MyFragment) object).notifyUpdate();
            }
            //don't return POSITION_NONE, avoid fragment recreation.
            return super.getItemPosition(object);
        }
    

1

以上提供的解决方案都对我无效。所以希望下面的解决方案对你有帮助。

我的代码中,我在viewPager中有2个片段。其中一个用于3个EditText和1个按钮,另一个片段具有RecyclerView。在单击按钮时,我的值将传递到recyclerView,但它没有更新。所以现在,我使用了以下代码:

enter image description here

我在按钮点击时调用了 notifyDataSetChanged()。我的 MainActivity 内部有一个扩展 FragmentStatePagerAdapter 类的适配器类。 因此,我使用 mainActivity.mMainAdapter.notifyDataSetChanged() 进行调用。希望对某些人有所帮助。

太好了!感谢您发布这个。这是唯一对我有效的解决方案。 - NightStalker

1

这里的每个答案对我来说都不完美,但将多个答案结合起来是正确的选择。

public final class SomeFragment extends FragmentStatePagerAdapter{
    private final List<Fragment> fragments;
    private Fragment removeFragment; //Fragment to be removed in the next notifydatasetchanged


    @Override
    public int getItemPosition(final Object object) {
       return object.equals(this.removeFragment) ? FragmentStatePagerAdapter.POSITION_NONE : this.fragments.indexOf(object);
    }

}

仅为您希望从viewpager中移除的片段返回POSITION_NONE。其他所有片段仍在您的片段列表中。在调用notifyDataSetChanged()之前,请不要忘记从列表中删除“removeFragment”。

0
对于那些在尝试上述方法后仍然面临刷新问题的人:

使viewPager无效,然后调用notifyDataSetChanged()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接