使用FragmentStateAdapter移除viewPager2中的片段,但仍显示 [英] remove fragment in viewPager2 use FragmentStateAdapter, but still display

查看:3109
本文介绍了使用FragmentStateAdapter移除viewPager2中的片段,但仍显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个viewPager2和FragmentStateAdapter,并且有Fragement1、2、3、4,我在fragment2中,想要删除fragment3,并在fragment2之后显示fragment4。
问题是它总是向我显示fragment3(data),调试显示fragment3已被删除,但是显示的页面仍然具有fragment3内容。

I have a viewPager2 and FragmentStateAdapter, and there are Fragement1, 2,3 4, I am in fragment2, and want to remove fragment3, and display fragment4 after fragment2. The problem is it always show me fragment3(data), the debug shows the fragment3 has been removed, but the displayed page still has fragment3 content.

适配器:

class TipsAdapter(
private val items: MutableList<TripPage>,
context: FragmentActivity
) : FragmentStateAdapter(context) {

private val fragmentFactory = context.supportFragmentManager.fragmentFactory
private val classLoader = context.classLoader

override fun getItemCount(): Int = items.size

override fun createFragment(position: Int): Fragment {
    val pageInfo = items[position]
    val fragment = fragmentFactory.instantiate(classLoader, pageInfo.fragmentClass.name)
    fragment.arguments = Bundle().also { it.putParcelable(PAGE_INFO, pageInfo) }
    return fragment
}

fun getFragmentName(position: Int) = items[position].fragmentClass.simpleName

fun removeFragment(position: Int) {
    items.removeAt(position)
    notifyItemRemoved(position)
    notifyItemRangeChanged(position, items.size)
    notifyDataSetChanged()
}

}

删除片段代码:

      if ((view_pager.adapter as TipsAdapter).getFragmentName(index + 1).equals(
            TripPreFragment::class.simpleName) &&
            viewModel.shouldRemoveBulkApply()) {
            (view_pager.adapter as TipsAdapter).removeFragment(index + 1)
            view_pager.setCurrentItem(index + 1, true)
        } else {
            view_pager.setCurrentItem(index + 1, true)
        }


推荐答案

最后,它对我有用。当我们调用 notifyDataSetChanged()时,android将在适配器中调用
方法 getItemId()来检查是否该项目是否已更新。它返回源代码中的位置。这意味着在列表 0..i..n 中,如果删除 i ,它将变为 0 ... i ... n-1 i 不会更改,数据也不会自动更新。

Finally, it works for me. when we call notifyDataSetChanged(), android will call method getItemId() in adapter, to check if the item has been updated or not. it returns the position in source code. which means in list 0..i..n, if you remove i , it becomes to 0...i...n-1, the i won't change and the data won't update in adater.

    /**
 * Default implementation works for collections that don't add, move, remove items.
 * <p>
 * TODO(b/122670460): add lint rule
 * When overriding, also override {@link #containsItem(long)}.
 * <p>
 * If the item is not a part of the collection, return {@link RecyclerView#NO_ID}.
 *
 * @param position Adapter position
 * @return stable item id {@link RecyclerView.Adapter#hasStableIds()}
 */
@Override
public long getItemId(int position) {
    return position;
}

您需要做的就是重写此方法,然后 containsItem(long)

what you need to do is rewrite this method and containsItem(long),

对于我的情况,我使用每个片段的哈希码:

for my case, I use the hashcode of each fragment:

class TipsAdapter(
     private val items: MutableList<TripPreferencesOptimizerPage>,
     context: FragmentActivity
    ) : FragmentStateAdapter(context) {

private val fragmentFactory = context.supportFragmentManager.fragmentFactory
private val classLoader = context.classLoader
private val pageIds= items.map { it.hashCode().toLong() }

override fun getItemCount(): Int = items.size

override fun createFragment(position: Int): Fragment {
    val pageInfo = items[position]
    val fragment = fragmentFactory.instantiate(classLoader, pageInfo.fragmentClass.name)
    fragment.arguments = Bundle().also { it.putParcelable(PAGE_INFO, pageInfo) }
    return fragment
}

fun getFragmentName(position: Int) = items[position].fragmentClass.simpleName

fun removeFragment(position: Int) {
    items.removeAt(position)
    notifyItemRangeChanged(position, items.size)
    notifyDataSetChanged()
}

override fun getItemId(position: Int): Long {
    return items[position].hashCode().toLong() // make sure notifyDataSetChanged() works
}

override fun containsItem(itemId: Long): Boolean {
    return pageIds.contains(itemId)
}

}

这篇关于使用FragmentStateAdapter移除viewPager2中的片段,但仍显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆