【问题标题】:remove fragment in viewPager2 use FragmentStateAdapter, but still display删除 viewPager2 中的片段使用 FragmentStateAdapter,但仍显示
【发布时间】: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

标签: android android-viewpager fragmentstatepageradapter android-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)
}
}

【讨论】:

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