Android低版本下Fragment重新打开后ViewPager2图片不加载如何解决
问题根因分析
这个问题仅出现在Android 6及更低版本,核心是两个兼容问题叠加导致的:
- 低版本Android对未attach到Window的View的
post()任务执行逻辑有差异:Android 7.0+会在下一个渲染帧直接执行未attach View的post任务,而Android 6及更低版本会将任务挂起,直到View正式attach到Window才会执行。你在onBindViewHolder中用thumbnail.post()包裹Glide加载逻辑,Fragment重建时ViewPager2的ItemView还没完成attach,加载任务就被挂起,只有滑动时ItemView重新触发attach,任务才会执行、图片才会加载。 - ViewPager2默认的离屏加载逻辑在低版本Fragment重建场景下存在兼容缺陷,首次布局不会主动触发所有可见Item的绑定流程,只有滑动触发页面切换才会重新走绑定逻辑。
解决方案
1. 移除
onBindViewHolder中多余的post()包裹
onBindViewHolder执行时ItemView已经绑定到RecyclerView父布局,不需要额外用post延迟加载逻辑,这是导致低版本加载卡住的核心诱因。
2. 调整Glide生命周期绑定
将Glide的生命周期和Fragment的viewLifecycleOwner绑定,避免Fragment销毁重建时Glide请求被意外取消、不会自动重启。
3. 显式设置ViewPager2的离屏加载数量
避免默认懒加载逻辑在低版本不触发首次加载,根据你的页面数量设置合理的offscreenPageLimit即可。
4. Fragment销毁时清理ViewPager2的Adapter
避免旧的Adapter实例残留导致重建时加载异常。
修改后的代码示例
Fragment 逻辑调整
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val media = utilities.getMedia(this) val mediaList = media.toMutableList() // 传入viewLifecycleOwner给Adapter val adapter = ViewPagerAdapter(mediaList, viewLifecycleOwner) photo_view_pager.adapter = adapter // 根据你的图片数量设置离屏加载数,最少设置为1 photo_view_pager.offscreenPageLimit = minOf(mediaList.size - 1, 2) // 低版本兼容:手动触发一次Item刷新 photo_view_pager.post { adapter.notifyItemRangeChanged(0, adapter.itemCount) } } override fun onDestroyView() { // 销毁View时清空Adapter,避免旧实例残留 photo_view_pager.adapter = null super.onDestroyView() }
ViewPagerAdapter 逻辑调整
class ViewPagerAdapter ( private val images: List<Media>, // 新增LifecycleOwner参数用于Glide生命周期绑定 private val lifecycleOwner: LifecycleOwner ) : RecyclerView.Adapter<ViewPagerAdapter.ViewPagerViewHolder>() { inner class ViewPagerViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_picture, parent, false) return ViewPagerViewHolder(view) } override fun getItemCount(): Int = images.size override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) { val curImageUri = images[position].uri val thumbnail = holder.itemView.image_preview // 移除post包裹,直接用lifecycleOwner绑定Glide加载 Glide.with(lifecycleOwner) .load(curImageUri) // 可选:设置占位图避免加载过程中空白 .placeholder(R.drawable.default_placeholder) .diskCacheStrategy(DiskCacheStrategy.RESOURCE) .into(thumbnail) } }
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

