BottomSheet关闭后如何正确更新FragmentStateAdapter中的展示卡片
问题成因
- Adapter中存储的
fragment实例是最后一次调用createFragment方法生成的实例,而非当前ViewPager2正展示的Fragment实例。比如滑动时ViewPager2会预加载相邻页面,你存的实例实际是预加载的页面对象,和当前显示的页面不匹配。 - 即便你拿到的是当前展示的Fragment实例,调用
updateCard时也可能因Fragment生命周期问题触发空指针:如果该Fragment还未执行完onCreateView,或者已经被回收销毁、视图已解绑,lateinit修饰的crdNameTB1还未初始化/已经被回收,访问就会抛出空对象异常。 - 全局存储Activity作为伴生对象、直接持有Fragment实例调用视图方法的设计本身不符合Android组件生命周期规范,很容易出现生命周期脱钩的问题,还会引发内存泄漏。
解决方案
核心逻辑是先更新数据源,再通知Adapter刷新对应位置,不要直接持有Fragment实例调用视图方法:
- 首先修改
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) } }
- 修改
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 // 其他视图渲染逻辑 } } }
- 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
相关产品推荐
相关产品推荐

