删除 viewPager2 中的片段使用 FragmentStateAdapter,但仍显示

Posted

技术标签:

【中文标题】删除 viewPager2 中的片段使用 FragmentStateAdapter,但仍显示【英文标题】:remove fragment in viewPager2 use FragmentStateAdapter, but still display 【发布时间】:2020-01-16 05:35:51 【问题描述】:

我有viewPager2和FragmentStateAdapter,还有Fragment1,2,3 4,我在fragment2,想去掉fragment3,在fragment2之后显示fragment4。 问题是它总是显示片段3(数据),调试显示片段3已被删除,但显示的页面仍然有片段3内容。

适配器:

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)
        

【问题讨论】:

我有 2 个片段 mainfragment 和 otherfragment 。我在每 5 个位置之后添加 otherfragment 并且它不在 arraylist 中,那么如果它不在 list 中,如何删除该 otherfragment ?我正在使用 viewpager2 【参考方案1】:

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

就我而言,我使用每个片段的哈希码:

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)


【讨论】:

请找到更多有用的信息:***.com/questions/7263291/… 哇,你太棒了!你拯救了这一天:) 干杯 @Xianwei 这是 API 的一个完全不同的部分,不幸的是不相关 我花了几个小时试图解决这个问题。 Android 的不幸之处在于,它并不总是直观的,而且关于这些用例的文档也不完整。 对我来说每次更新号码也需要重新初始化pageIds = items.map it.hashCode().toLong()

以上是关于删除 viewPager2 中的片段使用 FragmentStateAdapter,但仍显示的主要内容,如果未能解决你的问题,请参考以下文章

ViewPager2 无法动态添加删除片段

ViewPager2 中的片段在返回父片段时被重新创建

如何更新 Tablayout 中的片段? (Viewpager2, FragmentStateAdapter)

ViewPager2:以编程方式选择特定片段

从 Viewpager2 片段访问父片段函数

响应Activity中的ViewPager2 Fragments事件