ViewPager2 notifyItemChanged 的 FragmentStateAdapter 未按预期工作
FragmentStateAdapter for ViewPager2 notifyItemChanged not working as expected
我正在将 ViewPager2 与 FragmentStateAdapter 一起使用,并且正在调用 notifyItemChanged(position)。但正如预期的那样,createFragment 方法没有再次调用。这是预期的行为还是错误,我应该怎么做
我的代码是
class EEditionPagerAdapter(
fragmentManager: FragmentManager, lifecycle: Lifecycle, private var date: String
) : FragmentStateAdapter(fragmentManager, lifecycle) {
private var menuList = emptyList<EEditionMenu>()
override fun getItemCount(): Int = menuList.size
override fun createFragment(position: Int): Fragment {
val menu = menuList[position]
return EEditionListingFragment.newInstance(menu, date)
}
fun submitList(list: List<EEditionMenu>) {
menuList = list
notifyItemRangeChanged(0, menuList.size)
}
fun changeDate(date: String, position: Int){
this.date = date
notifyItemChanged(position)
}
}
当您为 FragmentStateAdapter 调用 notifyItemChanged 时,它会调用 ensureFragment(position)
恢复已创建的片段
private void ensureFragment(int position) {
long itemId = getItemId(position);
if (!mFragments.containsKey(itemId)) {
// TODO(133419201): check if a Fragment provided here is a new Fragment
Fragment newFragment = createFragment(position);
newFragment.setInitialSavedState(mSavedStates.get(itemId));
mFragments.put(itemId, newFragment);
}
}
尝试覆盖 onBindViewHolder 并将日期设置为片段
override fun onBindViewHolder(
holder: FragmentViewHolder,
position: Int,
payloads: MutableList<Any>
) {
super.onBindViewHolder(holder, position, payloads)
val fragment: EEditionListingFragment? = fragmentManager.findFragmentByTag("f$position") as EEditionListingFragment?
fragment.updateDate(date)
}
放入FragementStateAdapter.class中mFragment的片段由
管理
void placeFragmentInViewHolder(@NonNull final FragmentViewHolder holder)
方法,它是包私有的,我们无权访问,在此方法中,片段被添加到带有标签 "f" + holder.getItemId()
的 mFragment 管理器中,与 "f" + position
.[=21 相同=]
scheduleViewAttach(fragment, container);
mFragmentManager.beginTransaction()
.add(fragment, "f" + holder.getItemId())
.setMaxLifecycle(fragment, STARTED)
.commitNow();
mFragmentMaxLifecycleEnforcer.updateFragmentMaxLifecycle(false);
因此,我们可以覆盖 onBindViewHolder
方法,同时显示碎片。
@Override
public void onBindViewHolder(@NonNull FragmentViewHolder holder, int position, @NonNull List<Object> payloads) {
super.onBindViewHolder(holder, position, payloads);
if (position == 0) {
String fragmentTag = "f" + holder.getItemId();
Log.v(TAG,"fragmentTag is : " + fragmentTag);
MyFragment fragment0 = (MyFragment) this.mFragmentManger.findFragmentByTag(fragmentTag);
if (fragment0 != null) {
Log.v(TAG,"onBindViewHolder updating fragment ...");
// do what ever you want to update the MyFragment
fragment0.update(payloads);
} else {
Log.v(TAG,"onBindViewHolder called, but fragment0 is null!");
}
}
}
在我的例子中,this.mFragmentManager
是通过构造函数兑现的。
public MyFragmentStateAdapter(@NonNull Fragment fragment) {
super(fragment); // this calls the fragment.getChildFragmentManager().
this.mFragmentManger = fragment.getChildFragmentManager();
}
而 createFragment()
是:
@NonNull
@Override
public Fragment createFragment(int position) {
if(position == 0){
if (this.fragment0 == null) {
this.fragment0 = MyFragment.getInstance();
}
return this.fragment0;
} else {
Log.v(TAG, "position " + position + " is called");
return null;
}
}
最后,在别处调用更新触发更新:
ViewPager2.getAdapter().notifyItemChanged(0, null);
// 0 is the fragment position of the fragment0 and null is payload.
FragmentStateAdapter 使用项目 ID 来确定片段是否已创建并重用已创建的片段。默认情况下,项目 ID 是项目的位置。您可以覆盖 getItemId
和 containsItem
以根据位置和日期提供您自己的唯一 ID,然后它会在日期更改时请求新片段。
我正在将 ViewPager2 与 FragmentStateAdapter 一起使用,并且正在调用 notifyItemChanged(position)。但正如预期的那样,createFragment 方法没有再次调用。这是预期的行为还是错误,我应该怎么做
我的代码是
class EEditionPagerAdapter(
fragmentManager: FragmentManager, lifecycle: Lifecycle, private var date: String
) : FragmentStateAdapter(fragmentManager, lifecycle) {
private var menuList = emptyList<EEditionMenu>()
override fun getItemCount(): Int = menuList.size
override fun createFragment(position: Int): Fragment {
val menu = menuList[position]
return EEditionListingFragment.newInstance(menu, date)
}
fun submitList(list: List<EEditionMenu>) {
menuList = list
notifyItemRangeChanged(0, menuList.size)
}
fun changeDate(date: String, position: Int){
this.date = date
notifyItemChanged(position)
}
}
当您为 FragmentStateAdapter 调用 notifyItemChanged 时,它会调用 ensureFragment(position)
恢复已创建的片段
private void ensureFragment(int position) {
long itemId = getItemId(position);
if (!mFragments.containsKey(itemId)) {
// TODO(133419201): check if a Fragment provided here is a new Fragment
Fragment newFragment = createFragment(position);
newFragment.setInitialSavedState(mSavedStates.get(itemId));
mFragments.put(itemId, newFragment);
}
}
尝试覆盖 onBindViewHolder 并将日期设置为片段
override fun onBindViewHolder(
holder: FragmentViewHolder,
position: Int,
payloads: MutableList<Any>
) {
super.onBindViewHolder(holder, position, payloads)
val fragment: EEditionListingFragment? = fragmentManager.findFragmentByTag("f$position") as EEditionListingFragment?
fragment.updateDate(date)
}
放入FragementStateAdapter.class中mFragment的片段由
管理void placeFragmentInViewHolder(@NonNull final FragmentViewHolder holder)
方法,它是包私有的,我们无权访问,在此方法中,片段被添加到带有标签 "f" + holder.getItemId()
的 mFragment 管理器中,与 "f" + position
.[=21 相同=]
scheduleViewAttach(fragment, container);
mFragmentManager.beginTransaction()
.add(fragment, "f" + holder.getItemId())
.setMaxLifecycle(fragment, STARTED)
.commitNow();
mFragmentMaxLifecycleEnforcer.updateFragmentMaxLifecycle(false);
因此,我们可以覆盖 onBindViewHolder
方法,同时显示碎片。
@Override
public void onBindViewHolder(@NonNull FragmentViewHolder holder, int position, @NonNull List<Object> payloads) {
super.onBindViewHolder(holder, position, payloads);
if (position == 0) {
String fragmentTag = "f" + holder.getItemId();
Log.v(TAG,"fragmentTag is : " + fragmentTag);
MyFragment fragment0 = (MyFragment) this.mFragmentManger.findFragmentByTag(fragmentTag);
if (fragment0 != null) {
Log.v(TAG,"onBindViewHolder updating fragment ...");
// do what ever you want to update the MyFragment
fragment0.update(payloads);
} else {
Log.v(TAG,"onBindViewHolder called, but fragment0 is null!");
}
}
}
在我的例子中,this.mFragmentManager
是通过构造函数兑现的。
public MyFragmentStateAdapter(@NonNull Fragment fragment) {
super(fragment); // this calls the fragment.getChildFragmentManager().
this.mFragmentManger = fragment.getChildFragmentManager();
}
而 createFragment()
是:
@NonNull
@Override
public Fragment createFragment(int position) {
if(position == 0){
if (this.fragment0 == null) {
this.fragment0 = MyFragment.getInstance();
}
return this.fragment0;
} else {
Log.v(TAG, "position " + position + " is called");
return null;
}
}
最后,在别处调用更新触发更新:
ViewPager2.getAdapter().notifyItemChanged(0, null);
// 0 is the fragment position of the fragment0 and null is payload.
FragmentStateAdapter 使用项目 ID 来确定片段是否已创建并重用已创建的片段。默认情况下,项目 ID 是项目的位置。您可以覆盖 getItemId
和 containsItem
以根据位置和日期提供您自己的唯一 ID,然后它会在日期更改时请求新片段。