我无法更新 ViewPager 中的内容。
FragmentPagerAdapter 类中方法 instantiateItem() 和 getItem() 的正确用法是什么?
我只使用 getItem() 来实例化并返回我的片段:
@Override
public Fragment getItem(int position) {
return new MyFragment(context, paramters);
}
这运作良好。除了我不能改变内容。
所以我发现了这个:ViewPager PagerAdapter not updating the View
“我的方法是对 instanceItem() 方法中的任何实例化视图使用 setTag() 方法”
现在我想实现 instantiateItem() 来做到这一点。但我不知道我必须返回什么(类型是 Object)以及与 getItem(int position) 的关系是什么?
我阅读了reference:
public abstract Fragment getItem(int position) 返回与指定位置关联的 Fragment。 public Object instantiateItem (ViewGroup container, int position) 为给定位置创建页面。适配器负责将视图添加到此处给出的容器中,尽管它只必须确保在它从 finishUpdate(ViewGroup) 返回时完成此操作。参数 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);
}
}
我的片段适配器
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;
}
}
我的片段
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
使用 FragmentPagerAdapter 或 FragmentStatePagerAdapter 时,最好只处理 getItem()
而根本不接触 instantiateItem()
。 PagerAdapter 上的 instantiateItem()
-destroyItem()
-isViewFromObject()
接口是一个较低级别的接口,FragmentPagerAdapter 使用它来实现更简单的 getItem()
接口。
在进入这个之前,我应该澄清一下
如果要切换出正在显示的实际片段,则需要避免使用 FragmentPagerAdapter 并使用 FragmentStatePagerAdapter。
该答案的早期版本错误地将 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 中删除。
不要从 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
}
Fragment
的问题,看看:stackoverflow.com/questions/19891828/…
d page on refreshes the 1-st page only after swiping pages? thw 2
d 页面始终为空白。谢谢
对于那些仍然面临与我之前遇到的相同问题的人,当我有一个包含 7 个片段的 ViewPager
时。这些片段的默认设置是从 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;
}
像魅力一样工作
https://i.stack.imgur.com/COX7R.png
序列化的数据必须加载到内存中。这可以使用 CursorLoader/AsyncTask/Thread 来完成。是否自动加载取决于您的代码。如果您使用的是 CursorLoader,它会自动加载,因为有一个注册的数据观察者。在调用 viewpager.setAdapter(pageradapter) 之后,适配器的 getCount() 会不断被调用来构建片段。因此,如果正在加载数据,getCount() 可以返回 0,因此您无需为没有显示的数据创建虚拟片段。数据加载完成后,由于getCount()还是0,适配器不会自动构建分片,所以我们可以设置getCount()返回实际加载的数据个数,然后调用适配器的notifyDataSetChanged()。 ViewPager 开始通过内存中的数据创建片段(仅前 2 个片段)。它在 notifyDataSetChanged() 返回之前完成。然后 ViewPager 有你需要的正确片段。如果数据库和内存中的数据都被更新(直写),或者只是内存中的数据被更新(回写),或者只有数据库中的数据被更新。在最后两种情况下,如果数据没有自动从数据库加载到内存(如上所述)。 ViewPager 和分页适配器只处理内存中的数据。所以当内存中的数据更新时,我们只需要调用适配器的 notifyDataSetChanged() 即可。由于已经创建了fragment,所以在notifyDataSetChanged()返回之前会调用适配器的onItemPosition(),getItemPosition()不需要做任何事情,然后更新数据。
notifyDataSetChanged()
然后自动更新,因为我使用的片段(带有图表视图)会自行刷新。如果不是,就像一个静态片段,我将不得不调用 onItemPositon()
并返回 POSITION_NONE
对此感到抱歉
在代码中的 notifyDataSetChanged()
之后在 ViewPager 上尝试 destroyDrawingCache()
。
Fragments
。所以谢谢!
经过数小时的挫折,同时尝试了上述所有解决方案来克服这个问题,并尝试了许多其他类似问题的解决方案,例如 this、this 和 this,但我都无法解决这个问题并做出 {4 } 来销毁旧的 Fragment
并用新的 Fragment
填充 pager
。我已经解决了以下问题:
1) 使 ViewPager
类扩展 FragmentPagerAdapter
,如下所示:
public class myPagerAdapter extends FragmentPagerAdapter {
2) 为存储 title
和 fragment
的 ViewPager
创建一个项目,如下所示:
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) 通过直接从 fragmentManager
本身删除所有以前的 fragment
来创建一个用新数据重新设置 adapter
数据的方法,以使 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;
}
5) 从容器 Activity
或 Fragment
中不要使用新数据重新初始化适配器。通过方法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();
我希望它有所帮助。
出于某种原因,没有一个答案对我有用,所以我不得不重写 restoreState 方法而不在我的 fragmentStatePagerAdapter 中调用 super。代码:
private class MyAdapter extends FragmentStatePagerAdapter {
// [Rest of implementation]
@Override
public void restoreState(Parcelable state, ClassLoader loader) {}
}
restoreState
在 FragmentStatePagerAdapter
的更高版本中被标记为最终版本。
我稍微修改了比尔菲利普斯提供的解决方案以满足我的需要
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 中)
我有一个类似的问题,但不想相信现有的解决方案(硬编码标签名称等),我无法让 M-WaJeEh 的解决方案为我工作。这是我的解决方案:
我将在 getItem 中创建的片段的引用保存在一个数组中。只要活动没有因配置更改或内存不足或其他原因而被破坏(-->返回活动时,片段返回到它们的最后状态而不会再次调用“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;
}
所以,一方面我很高兴我找到了一个适合我的解决方案并想与你分享,但我也想问其他人是否尝试过类似的东西以及我是否有任何理由不应该这样做这样做吗?到目前为止,它对我来说非常好......
public void destroyItem(ViewGroup container, int position, Object object)
中从 myFragments
中删除该项目,这样您就不会获取过时的片段引用。
我也遇到过同样的问题,而且我搜索了太多次。在 stackoverflow 或通过谷歌给出的任何答案都不能解决我的问题。我的问题很简单。我有一个列表,我用 viewpager 显示这个列表。当我将一个新元素添加到列表的头部并刷新 viewpager 时,什么都没有改变。我的最终解决方案非常简单,任何人都可以使用。当一个新元素添加到列表中并且想要刷新列表时。首先将 viewpager 适配器设置为 null 然后重新创建适配器并将 i 设置为 viewpager。
myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);
确保您的适配器必须扩展 FragmentStatePagerAdapter
我使用 EventBus 库来更新 ViewPager
中的 Fragment
内容。逻辑很简单,就像 document of EventBus how to do。无需控制 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 中,有一个公共整数“页面”,它可以告诉我是否是我要刷新的页面。
public class FragmentsMain extends Fragment {
private Cursor cursor;
private static Context context;
public int page=-1;
我知道派对迟到了。我通过在 FragmentPagerAdapter#notifyDataSetChanged();
之后调用 TabLayout#setupWithViewPager(myViewPager);
解决了这个问题
如果您想使用 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 存在可能会或可能不会给您的用例带来麻烦的问题。
此外,链接也很少有解决方案..很少有可能适合您的要求。
这可能对某人有帮助 - 在我的情况下,当插入新页面时,视图寻呼机两次询问现有片段的位置,但不询问新项目的位置,导致不正确的行为和数据不显示。
复制 FragmentStatePagerAdapter 的源代码(似乎很久没有更新了)。覆盖 notifyDataSetChanged() @Override public void notifyDataSetChanged() { mFragments.clear(); super.notifyDataSetChanged();向 destroyItem() 添加完整性检查以防止崩溃: if (position < mFragments.size()) { mFragments.set(position, null); }
这是我的实现,它结合了来自@Bill Phillips One 的信息,大多数情况下都会获取片段缓存,除非数据发生了变化。很简单,而且似乎工作正常。
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);
}
}
我的活动.java
mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
此解决方案不适用于所有人,但就我而言,我的 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);
}
}
}
如果您有同一个片段的多个版本,您可以使用相同的策略来调用这些片段上的方法,以确定它是否是您要更新的片段。
我已经浏览了上面的所有答案和其他一些帖子,但仍然找不到适合我的东西(具有不同的片段类型以及动态添加和删除选项卡)。 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);
}
}
如果要基于索引重新创建或重新加载片段,请使用 FragmentStatePagerAdapter 而不是 FragmentPagerAdapter 例如,如果要重新加载 FirstFragment 以外的片段,可以像这样检查实例并返回位置
public int getItemPosition(Object item) {
if(item instanceof FirstFragment){
return 0;
}
return POSITION_NONE;
}
您需要更改 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() 时不会改变。
您可以运行此项目以确认如何工作。 https://github.com/cuichanghao/infivt
使用 ViewPager2
和 FragmentStateAdapter
:
ViewPager2
支持动态更新数据。
docs 中有一条关于如何使其工作的重要说明:
注意:DiffUtil 实用程序类依赖于通过 ID 识别项目。如果您使用 ViewPager2 对可变集合进行分页,则还必须覆盖 getItemId() 和 containsItem()。 (强调我的)
基于 ViewPager2
documentation 和 Android 的 Github sample project,我们需要采取一些步骤:
设置 FragmentStateAdapter 并覆盖以下方法:getItemCount、createFragment、getItemId 和 containsItem(注意:ViewPager2 不支持 FragmentStatePagerAdapter) 将适配器附加到 ViewPager2 使用 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!!)
}
FragmentStatePagerAdapter
时返回 POSITION_NONE,我也可以看到它删除了我的片段并创建了新实例。但是新实例会收到一个带有旧片段状态的 savedInstanceState Bundle。如何完全销毁片段,以便再次创建时 Bundle 为空?