动态更新ViewPager ?

我无法更新ViewPager中的内容。

FragmentPagerAdapter类中instantiateItem()和getItem()方法的正确用法是什么?

我只使用getItem()来实例化并返回我的片段:

@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}

这很有效。但我不能改变内容。

所以我找到了这个:ViewPager PagerAdapter不更新View

我的方法是对instantiateItem()方法中的任何实例化视图使用setTag()方法

现在我想实现instantiateItem()来实现这一点。但我不知道我必须返回什么(类型是对象)和什么与getItem(int位置)的关系?

我读了参考:

  • 公共抽象片段getItem (int position)

    .返回与指定位置相关的片段
  • 公共对象实例化项目(ViewGroup容器,int位置)

    为给定位置创建页面。适配器负责将视图添加到这里给出的容器中,尽管它只需要确保在从finishUpdate(ViewGroup)返回时完成此操作。 参数< / p >

    container页面将在其中显示的视图。 position要实例化的页面位置

    返回

    返回一个表示新页面的对象。这并不需要是一个视图,但可以是页面的其他容器

但我还是不明白

这是我的代码。我用的是v4支持包。

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
private ViewPager pager;
private MyFragmentAdapter adapter;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pager1);


pager = (ViewPager)findViewById(R.id.slider);


String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};


adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
pager.setAdapter(adapter);


((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
reload();
}
});
}


private void reload() {
String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
//adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
adapter.setData(data);
adapter.notifyDataSetChanged();
pager.invalidate();


//pager.setCurrentItem(0);
}
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
private int slideCount;
private Context context;
private String[] data;


public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.data = data;
}


@Override
public Fragment getItem(int position) {
return new MyFragment(data[position], context);
}


@Override
public int getCount() {
return slideCount;
}


public void setData(String[] data) {
this.data = data;
}


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

MyFragment

public final class MyFragment extends Fragment {
private String text;


public MyFragment(String text, Context context) {
this.text = text;
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.slide, null);
((TextView)view.findViewById(R.id.text)).setText(text);


return view;
}
}
这里也有人有类似的问题,没有答案 http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html < / p >
300340 次浏览

当使用FragmentPagerAdapter或FragmentStatePagerAdapter时,最好只处理getItem()而根本不涉及instantiateItem()。PagerAdapter上的instantiateItem()-destroyItem()-isViewFromObject()接口是一个低级接口,FragmentPagerAdapter使用它来实现更简单的getItem()接口。

在讨论这个问题之前,我应该澄清这一点

如果你想切换出正在显示的实际片段,你需要避免FragmentPagerAdapter并使用 FragmentStatePagerAdapter。< /强> < / p >

这个答案的早期版本错误地使用了FragmentPagerAdapter作为示例——这是行不通的,因为FragmentPagerAdapter在第一次显示后永远不会破坏一个片段。

我不推荐你链接的帖子中提供的setTag()findViewWithTag()解决方案。正如你所发现的,使用setTag()findViewWithTag()不能与片段一起工作,所以它不是一个很好的匹配。

正确的解决方案是覆盖getItemPosition()。当notifyDataSetChanged()被调用时,ViewPager会对其适配器中的所有项调用getItemPosition(),以查看是否需要将它们移动到不同的位置或删除。

默认情况下,getItemPosition()返回POSITION_UNCHANGED,这意味着“该对象在其所在位置很好,不要销毁或删除它。”返回POSITION_NONE可以解决这个问题,而是说:“这个对象不再是我正在显示的项目,删除它。”因此,它可以删除和重新创建适配器中的每个项。

这是一个完全合法的修复!此修复使notifyDataSetChanged的行为像常规适配器一样,没有视图回收。如果您实现了这个修复并且性能令人满意,那么您就可以开始比赛了。工作。

如果你需要更好的性能,你可以使用更花哨的getItemPosition()实现。下面是一个寻呼机从字符串列表中创建片段的例子:

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();


FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
public int getCount() {
return titles.size();
}


public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
fragment.setTitle(titles.get(position));
return fragment;
}


public int getItemPosition(Object item) {
MyFragment fragment = (MyFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);


if (position >= 0) {
return position;
} else {
return POSITION_NONE;
}
}
});

使用这个实现,只显示显示新标题的片段。任何显示标题仍在列表中的片段将被移动到列表中的新位置,而标题已不在列表中的片段将被销毁。

如果片段没有被重新创建,但无论如何都需要更新,该怎么办?对活动片段的更新最好由片段本身处理。这就是拥有片段的好处,毕竟它是自己的控制器。片段可以向onCreate()中的另一个对象添加监听器或观察器,然后在onDestroy()中删除它,从而管理更新本身。你不必像在ListView或其他AdapterView类型的适配器中那样,将所有的更新代码放在getItem()中。

最后一件事-仅仅因为FragmentPagerAdapter不破坏片段并不意味着getItemPosition在FragmentPagerAdapter中完全无用。你仍然可以使用这个回调在ViewPager中重新排序你的片段。但是,它永远不会将它们完全从FragmentManager中移除。

在你的代码中notifyDataSetChanged()之后尝试ViewPager上的destroyDrawingCache()

不要从getItemPosition()返回POSITION_NONE并重新创建完整的视图,而是这样做:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
this.updateData = xyzData;
notifyDataSetChanged();
}


@Override
public int getItemPosition(Object object) {
if (object instanceof UpdateableFragment) {
((UpdateableFragment) object).update(updateData);
}
//don't return POSITION_NONE, avoid fragment recreation.
return super.getItemPosition(object);
}

你的片段应该实现UpdateableFragment接口:

public class SomeFragment extends Fragment implements
UpdateableFragment{


@Override
public void update(UpdateData xyzData) {
// this method will be called for every fragment in viewpager
// so check if update is for this fragment
if(forMe(xyzData)) {
// do whatever you want to update your UI
}
}
}

以及界面:

public interface UpdateableFragment {
public void update(UpdateData xyzData);
}

你的数据类:

public class UpdateData {
//whatever you want here
}
我遇到过这个问题,今天终于解决了,所以我把我学到的东西写下来,我希望这对那些刚接触Android的ViewPager和像我一样更新的人有帮助。我在API级别17中使用FragmentStatePagerAdapter,目前只有2个片段。我想一定有什么地方不对,请指正,谢谢。 enter image description here

  1. 序列化的数据必须加载到内存中。这可以使用CursorLoader/AsyncTask/Thread来完成。是否自动加载取决于您的代码。如果你正在使用CursorLoader,它是自动加载的,因为有一个注册的数据观察者。

  2. 在调用viewpager.setAdapter(pageradapter)之后,适配器的getCount()将不断被调用以构建片段。因此,如果正在加载数据,getCount()可以返回0,因此不需要为没有显示的数据创建虚拟片段。

  3. 数据加载后,适配器将不会自动构建片段,因为getCount()仍然是0,因此我们可以将实际加载的数据号设置为getCount()返回,然后调用适配器的notifyDataSetChanged()ViewPager开始通过内存中的数据创建片段(只是前2个片段)。它是在notifyDataSetChanged()返回之前完成的。然后ViewPager有你需要的正确片段。

  4. 如果数据库和内存中的数据都被更新(透写),或者只更新内存中的数据(回写),或者只更新数据库中的数据。在最后两种情况中,如果数据没有自动从数据库加载到内存(如上所述)。 ViewPager和寻呼机适配器只处理内存中的数据

  5. 因此,当内存中的数据更新时,我们只需要调用适配器的notifyDataSetChanged()。由于片段已经创建,适配器的onItemPosition()将在notifyDataSetChanged()返回之前被调用。在getItemPosition()中不需要做任何事情。然后更新数据。

我有一个类似的问题,但不想相信现有的解决方案(硬编码标签名称等),我不能让M-WaJeEh的解决方案为我工作。以下是我的解决方案:

我将对getItem中创建的片段的引用保存在一个数组中。只要活动没有因为configurationChange或内存不足或其他原因而被破坏,这就可以工作(——>当回到活动时,片段返回到它们的最后状态,而不会再次调用'getItem',因此不会更新数组)。

为了避免这个问题,我实现了instantiateItem(ViewGroup, int)并更新我的数组,像这样:

        @Override
public Object instantiateItem(ViewGroup container, int position) {
Object o = super.instantiateItem(container, position);
if(o instanceof FragmentX){
myFragments[0] = (FragmentX)o;
}else if(o instanceof FragmentY){
myFragments[1] = (FragmentY)o;
}else if(o instanceof FragmentZ){
myFragments[2] = (FragmentZ)o;
}
return o;
}

所以,一方面,我很高兴我找到了一个适合我的解决方案,并想与你们分享,但我也想问一下,是否有人尝试过类似的方法,是否有任何理由让我不应该这样做?到目前为止,它对我来说很好……

经过几个小时的挫折,同时尝试所有上述解决方案来克服这个问题,也尝试了其他类似问题的许多解决方案,如,这些都失败了,我解决这个问题,并使ViewPager破坏旧的Fragment,并用新的Fragment填充pager。我解决的问题如下:

使ViewPager类扩展FragmentPagerAdapter,如下所示:

 public class myPagerAdapter extends FragmentPagerAdapter {

2)ViewPager创建一个Item,用于存储titlefragment,如下所示:

public class PagerItem {
private String mTitle;
private Fragment mFragment;




public PagerItem(String mTitle, Fragment mFragment) {
this.mTitle = mTitle;
this.mFragment = mFragment;
}
public String getTitle() {
return mTitle;
}
public Fragment getFragment() {
return mFragment;
}
public void setTitle(String mTitle) {
this.mTitle = mTitle;
}


public void setFragment(Fragment mFragment) {
this.mFragment = mFragment;
}


}

3)使ViewPager的构造函数接受我的FragmentManager实例并将其存储在我的class中,如下所示:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;


public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
super(fragmentManager);
mFragmentManager = fragmentManager;
mPagerItems = pagerItems;
}

4)创建一个用新数据重新设置adapter数据的方法,方法是直接从fragmentManager本身删除之前的所有fragment,使adapter再次从新列表中设置新的fragment,如下所示:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
if (mPagerItems != null)
for (int i = 0; i < mPagerItems.size(); i++) {
mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
}
mPagerItems = pagerItems;
}

容器中的ActivityFragment不使用新数据重新初始化适配器。通过方法setPagerItems设置新数据,如下所示:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));


mPagerAdapter.setPagerItems(pagerItems);
mPagerAdapter.notifyDataSetChanged();

我希望这能有所帮助。

我稍微修改了Bill Phillips提供的解决方案,以满足我的需要

private class PagerAdapter extends FragmentStatePagerAdapter{
Bundle oBundle;
FragmentManager oFragmentManager;
ArrayList<Fragment> oPooledFragments;


public PagerAdapter(FragmentManager fm) {
super(fm);
oFragmentManager=fm;


}
@Override
public int getItemPosition(Object object) {


Fragment oFragment=(Fragment)object;
oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
if(oPooledFragments.contains(oFragment))
return POSITION_NONE;
else
return POSITION_UNCHANGED;
}
}

以便getItemPosition()仅为调用getItemPosition时当前在FragmentManager中的那些片段返回POSITION_NONE。 (注意,这个FragmentStatePager和与之相关的ViewPager包含在一个Fragment中,而不是在一个Activity中

对于那些仍然面临同样的问题,当我有一个ViewPager与7个片段。这些片段默认从API服务加载英语内容,但这里的问题是,我想从设置活动和完成后更改语言 设置活动我想在主活动ViewPager刷新片段以匹配用户的语言选择,并加载阿拉伯语内容,如果用户选择阿拉伯语在这里,我所做的工作从第一次

1-你必须使用FragmentStatePagerAdapter如上所述。

2-在mainActivity我覆盖onResume,并做以下

if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-i覆盖了mPagerAdapter中的getItemPosition(),并使其返回POSITION_NONE

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

工作很有魅力

我使用EventBus库来更新ViewPager中的Fragment内容。逻辑很简单,就像文档的EventBus如何做一样。不需要控制FragmentPagerAdapter实例。代码在这里:

1:定义事件

定义需要更新的消息。

public class UpdateCountEvent {
public final int count;


public UpdateCountEvent(int count) {
this.count = count;
}
}

2.准备用户

在需要更新的片段中编写以下代码。

@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}


@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}


public void onEvent(UpdateCountEvent event) {//get update message
Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.发布事件

将下面的代码写入其他Activity或其他需要更新参数的Fragment

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));

我尝试了很多不同的方法,但没有一个能真正解决我的问题。下面是我如何用你们提供的混合解决方案来解决这个问题。谢谢每一个人。

class PagerAdapter extends FragmentPagerAdapter {


public boolean flag_refresh=false;


public PagerAdapter(FragmentManager fm) {
super(fm);
}


@Override
public Fragment getItem(int page) {
FragmentsMain f;
f=new FragmentsMain();
f.page=page;
return f;
}


@Override
public int getCount() {
return 4;
}


@Override
public int getItemPosition(Object item) {
int page= ((FragmentsMain)item).page;


if (page == 0 && flag_refresh) {
flag_refresh=false;
return POSITION_NONE;
} else {
return super.getItemPosition(item);
}
}


@Override
public void destroyItem(View container, int position, Object object) {


((ViewPager) container).removeView((View) object);
}
}

我只想在onResume()后刷新页面0。

 adapter=new PagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);


@Override
protected void onResume() {
super.onResume();


if (adapter!=null) {
adapter.flag_refresh=true;
adapter.notifyDataSetChanged();
}
}

在我的FragmentsMain中,有一个公共整数“page”,它可以告诉我这是否是我想要刷新的页面。

public class FragmentsMain extends Fragment {


private Cursor cursor;
private static Context context;
public int page=-1;

由于某种原因,没有一个答案对我有用,所以我不得不重写restoreState方法,而不调用我的fragmentStatePagerAdapter中的super。代码:

private class MyAdapter extends FragmentStatePagerAdapter {


// [Rest of implementation]


@Override
public void restoreState(Parcelable state, ClassLoader loader) {}


}
如果你想使用FragmentStatePagerAdapter,请查看https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990。 FragmentStatePagerAdapter存在一些问题,可能会也可能不会给您的用例带来麻烦。< / p >

此外,link也有一些解决方案,少数可能适合您的要求。

我知道我要迟到了。我已经通过在FragmentPagerAdapter#notifyDataSetChanged();之后调用TabLayout#setupWithViewPager(myViewPager);来解决这个问题

这个解决方案并不适用于所有人,但在我的例子中,我的ViewPager中的每个Fragment都是一个不同的类,并且一次只存在其中一个。

有了这个约束,这个解决方案是安全的,应该可以安全地在生产中使用。

private void updateFragment(Item item) {


List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (Fragment fragment : fragments) {


if (fragment instanceof MyItemFragment && fragment.isVisible()) {
((MyItemFragment) fragment).update(item);
}


}
}

如果您有同一个片段的多个版本,您可以使用相同的策略来调用这些片段上的方法,以确定它是否是您希望更新的片段。

这可能对某些人有帮助-在我插入一个新页面时,视图寻呼机要求现有片段的位置两次,但没有要求新项目的位置,导致不正确的行为和数据不显示。

  1. 为FragmentStatePagerAdapter复制源代码(似乎已经很久没有更新了)。

  2. < p >覆盖notifyDataSetChanged ()

    @Override
    public void notifyDataSetChanged() {
    mFragments.clear();
    super.notifyDataSetChanged();
    }
    
  3. Add a sanity check to destroyItem() to prevent crashes:

    if (position < mFragments.size()) {
    mFragments.set(position, null);
    }
    

我已经浏览了上面所有的答案和其他一些帖子,但仍然找不到适合我的东西(不同的片段类型以及动态添加和删除选项卡)。FWIW遵循的方法对我来说是有效的(以防其他人有同样的问题)。

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
private static final String TAB1_TITLE = "Tab 1";
private static final String TAB2_TITLE = "Tab 2";
private static final String TAB3_TITLE = "Tab 3";


private ArrayList<String> titles = new ArrayList<>();
private Map<Fragment, Integer> fragmentPositions = new HashMap<>();




public MyFragmentStatePageAdapter(FragmentManager fm) {
super(fm);
}




public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
titles.clear();


if (showTab1) {
titles.add(TAB1_TITLE);
}
if (showTab2) {
titles.add(TAB2_TITLE);
}
if (showTab3) {
titles.add(TAB3_TITLE);
}
notifyDataSetChanged();
}




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


@Override
public Fragment getItem(int position) {
Fragment fragment = null;


String tabName = titles.get(position);
if (tabName.equals(TAB1_TITLE)) {
fragment =  Tab1Fragment.newInstance();
} else if (tabName.equals(TAB2_TITLE)) {
fragment =  Tab2Fragment.newInstance();
} else if (tabName.equals(TAB3_TITLE)) {
fragment =  Tab3Fragmen.newInstance();
}


((BaseFragment)fragment).setTitle(tabName);
fragmentPositions.put(fragment, position);
return fragment;
}


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


@Override
public int getItemPosition(Object item) {
BaseFragment fragment = (BaseFragment)item;
String title = fragment.getTitle();
int position = titles.indexOf(title);


Integer fragmentPosition = fragmentPositions.get(item);
if (fragmentPosition != null && position == fragmentPosition) {
return POSITION_UNCHANGED;
} else {
return POSITION_NONE;
}
}


@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
fragmentPositions.remove(object);
}
}

我遇到过同样的问题,我已经寻找过太多次了。任何在stackoverflow或通过谷歌给出的答案都不是我的问题的解决方案。我的问题很简单。我有一个列表,我用viewpager显示这个列表。当我添加一个新元素到列表的头,我刷新viewpager什么都没有改变。我的最终解决方案非常简单,任何人都可以使用。当一个新元素添加到列表中时,要刷新列表。首先将viewpager适配器设置为null,然后重新创建适配器并将i设置为viewpager。

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

确保您的适配器必须扩展FragmentStatePagerAdapter

使用FragmentStatePagerAdapter代替FragmentPagerAdapter 如果你想在索引基础上重新创建或重新加载片段 例如,如果你想重新加载FirstFragment以外的fragment,你可以检查instance并返回position,像这样

 public int getItemPosition(Object item) {
if(item instanceof FirstFragment){
return 0;
}
return POSITION_NONE;
}
这是我的实现,包含来自@Bill Phillips的信息 除非数据发生了变化,否则大多数情况下都会使用片段缓存。

MyFragmentStatePagerAdapter.java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
this.mIsUpdating = mIsUpdating;
}




@Override
public int getItemPosition(@NonNull Object object) {


if (mIsUpdating) {
return POSITION_NONE;
}
else {
return super.getItemPosition(object);
}
}

MyActivity.java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);

你需要改变instantiateItem的mFragments元素getItemPosition。

    if (mFragments.size() > position) {
Fragment f = mFragments.get(position);


if (f != null) {
int newPosition = getItemPosition(f);
if (newPosition == POSITION_UNCHANGED) {
return f;
} else if (newPosition == POSITION_NONE) {
mFragments.set(position, null);
} else {
mFragments.set(newPosition, f);
}
}
}

基于AndroidX FragmentStatePagerAdapter.java,因为mFragments的元素位置在调用notifyDataSetChanged()时不会改变。

< p >来源: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java < / p > < p >的例子: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt < / p >

你可以运行这个项目来确认如何工作。 https://github.com/cuichanghao/infivt < / p >

使用ViewPager2FragmentStateAdapter:

ViewPager2支持动态更新数据。

文档中有一个关于如何让它工作的重要说明:

注意:DiffUtil实用程序类依赖于通过ID标识项。如果使用ViewPager2对可变集合进行分页,则必须重写__ABC1和containsItem()(强调我的)

基于ViewPager2 文档和Android的Github 示例项目,我们需要采取几个步骤:

  1. 设置FragmentStateAdapter并覆盖以下方法:getItemCountcreateFragmentgetItemIdcontainsItem(注意:ViewPager2不支持FragmentStatePagerAdapter)

  2. 将适配器附加到ViewPager2

  3. 使用DiffUtil将调度列表更新到ViewPager2(不需要使用DiffUtil,如示例项目中所示)


例子:

private val items: List<Int>
get() = viewModel.items
private val viewPager: ViewPager2 = binding.viewPager


private val adapter = object : FragmentStateAdapter(this@Fragment) {
override fun getItemCount() = items.size
override fun createFragment(position: Int): Fragment = MyFragment()
override fun getItemId(position: Int): Long = items[position].id
override fun containsItem(itemId: Long): Boolean = items.any { it.id == itemId }
}
viewPager.adapter = adapter
    

private fun onDataChanged() {
DiffUtil
.calculateDiff(object : DiffUtil.Callback() {
override fun getOldListSize(): Int = viewPager.adapter.itemCount
override fun getNewListSize(): Int = viewModel.items.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
viewPager.adapter?.getItemId(oldItemPosition) == viewModel.items[newItemPosition].id


override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
areItemsTheSame(oldItemPosition, newItemPosition)
}, false)
.dispatchUpdatesTo(viewPager.adapter!!)
}