You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BottomSheet关闭后如何正确更新FragmentStateAdapter中的展示卡片

问题成因

  • Adapter中存储的fragment实例是最后一次调用createFragment方法生成的实例,而非当前ViewPager2正展示的Fragment实例。比如滑动时ViewPager2会预加载相邻页面,你存的实例实际是预加载的页面对象,和当前显示的页面不匹配。
  • 即便你拿到的是当前展示的Fragment实例,调用updateCard时也可能因Fragment生命周期问题触发空指针:如果该Fragment还未执行完onCreateView,或者已经被回收销毁、视图已解绑,lateinit修饰的crdNameTB1还未初始化/已经被回收,访问就会抛出空对象异常。
  • 全局存储Activity作为伴生对象、直接持有Fragment实例调用视图方法的设计本身不符合Android组件生命周期规范,很容易出现生命周期脱钩的问题,还会引发内存泄漏。

解决方案

核心逻辑是先更新数据源,再通知Adapter刷新对应位置,不要直接持有Fragment实例调用视图方法:

  1. 首先修改ScreenSlidePagerAdapter,移除全局持有的fragment变量,Fragment的生命周期交给FragmentStateAdapter自行管理:
public class ScreenSlidePagerAdapter(activity: AppCompatActivity, var items: ArrayList<Helpers.Card>, private val saveToDb: Boolean) : FragmentStateAdapter(activity) {
    override fun getItemCount(): Int = items.count()
    override fun createFragment(position: Int): Fragment{
        // 传入position即可,不需要把Adapter自身传给Fragment
        return CardItemFragment(position, saveToDb)
    }
}
  1. 修改CardItemFragment,视图渲染时直接从Adapter的数据源取最新的Card数据:
class CardItemFragment(val position:Int, val saveToDb: Boolean) : Fragment() {
    lateinit var cardView1: ConstraintLayout
    lateinit var crdNameTB1: TextView
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val v = inflater.inflate(R.layout.card_item, container, false)
        cardView1 = v.findViewById(R.id.cardView1)
        crdNameTB1= v.findViewById(R.id.crdNameTB1)
        return v
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 每次视图创建时都取最新的数据源渲染
        val currentCard = (requireActivity() as MainActivity).galleryPagerAdapter?.items?.getOrNull(position)
        currentCard?.let {
            crdNameTB1.text = it.name
            // 其他视图渲染逻辑
        }
    }
}
  1. BottomSheet关闭修改完Card的name属性后,先更新Adapter的数据源,再通知对应位置刷新即可:
// 取当前展示的卡片位置
val currentPos = mainActivity.viewPager2.currentItem
// 先更新数据源
MainActivity.galleryPagerAdapter?.items?.getOrNull(currentPos)?.name = 你修改后的新名称
// 通知Adapter刷新对应位置,会自动触发对应Fragment的重新渲染
MainActivity.galleryPagerAdapter?.notifyItemChanged(currentPos)

内容的提问来源于stack exchange,提问作者Askcomp eugi-tech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 19:12:03