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

Android Fragment内ArrayList自动重复扩容,Intent传参时大小异常

问题原因
  1. 核心问题为可变集合引用共享:Firestore回调返回的list是可变集合实例,你先后将该实例传给DealsAdapter、赋值给全局变量deals,三者持有同一个集合的引用。若任意一处修改了该集合(比如DealsAdapter为实现无限轮播效果首尾追加重复项、内部逻辑插入元素),全局deals的内容也会同步被修改,大小不断累加。
  2. 叠加调用时机问题:getDeals方法大概率在Fragment生命周期中被多次触发(比如onResume每次可见都调用、onCreateView每次重建视图都调用),每次回调拿到的集合已经被之前的逻辑修改过,赋值给deals后大小就会持续增长。
  3. 隐藏放大问题:你在successDeals中每次调用都重复给ViewPager2注册OnPageChangeCallback、重复创建Handler和Runnable,从未做移除操作,既会导致内存泄漏,也会多次触发轮播逻辑,进一步提升集合被修改的概率。
解决方案

1. 切断集合引用共享,每次使用都做独立拷贝

修改getDeals的成功回调逻辑,不要直接使用Firestore返回的list引用,每次都创建新的ArrayList拷贝内容,避免不同组件共享同一个集合,同时删除无意义的deals.clear()代码:

private fun getDeals() {
    FirestoreClass().getDeals(
        onSuccess = { list ->
            Result.success(list)
            // 给successDeals传独立拷贝的集合
            successDeals(ArrayList(list))
            // 全局deals也用独立拷贝,不要直接赋值引用
            deals = ArrayList(list)
            Log.d("Tag1", "Size is ${deals.size}")
        },
        onFailure = {
        }
    )
}

2. 避免重复调用和重复注册监听

  • 把getDeals的调用放到onCreate中,而非onCreateView/onResume,保证Fragment生命周期内仅调用一次,确有刷新需求再主动触发。
  • 修改successDeals逻辑,每次注册回调前先移除旧回调,同时在Fragment销毁视图时清理资源:
private fun successDeals(list: ArrayList<Deals>) {
    Log.d("Tag3", "Size is ${deals.size}")
    if (list.size > 0) {
        binding.vpDeals.visibility = View.VISIBLE
        // 先移除旧的页面变化回调
        binding.vpDeals.clearOnPageChangeCallbacks()
        val adapter = DealsAdapter(binding.vpDeals,requireContext(), list)
        binding.vpDeals.adapter = adapter
        binding.vpDeals.orientation = ViewPager2.ORIENTATION_HORIZONTAL
        // 先移除之前的Handler任务
        sliderHandle.removeCallbacks(sliderRun)
        sliderRun= Runnable {
            binding.vpDeals.currentItem=binding.vpDeals.currentItem+1
        }
        binding.vpDeals.registerOnPageChangeCallback(
            object :ViewPager2.OnPageChangeCallback(){
                override fun onPageSelected(position: Int) {
                    super.onPageSelected(position)
                    sliderHandle.removeCallbacks(sliderRun)
                    sliderHandle.postDelayed(sliderRun,4000)
                }
            }
        )
    } else {
        binding.vpDeals.visibility = View.GONE
    }
}

// 补充生命周期资源清理逻辑
override fun onDestroyView() {
    sliderHandle.removeCallbacks(sliderRun)
    binding.vpDeals.clearOnPageChangeCallbacks()
    super.onDestroyView()
}

3. 可选语法防护

若要从根源避免集合被意外修改,可以把deals声明为只读列表:

// 替换原来的可变列表声明
private var deals: List<Deals> = emptyList()

后续修改必须重新赋值整个列表,从语法层面禁止集合内容被局部逻辑意外修改。

内容的提问来源于stack exchange,提问作者Codist

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 23:06:06