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

如何用协程在后台线程过滤ArrayList?Adapter无法观察LiveData求助

解决方案:将LiveData观察逻辑移至Fragment,而非Adapter

Adapter的核心职责是绑定数据到视图,它不应该持有LiveData的观察逻辑——这会导致生命周期不匹配(Adapter没有LifecycleOwner),进而引发内存泄漏或UI异常。正确的做法是把LiveData的观察放在Fragment中,再将过滤后的结果传递给子Adapter。

步骤1:修正ViewModel的LiveData命名与逻辑

先规范ViewModel中LiveData的命名(下划线开头对应私有MutableLiveData,对外暴露不可变的LiveData),并确保过滤后的数据正确转为MutableList:

class MainFragmentViewModel : ViewModel() {
    // 私有可变LiveData,仅内部更新
    private val _filterGoldList = MutableLiveData<MutableList<Item>>()
    // 对外暴露不可变的LiveData
    val filterGoldList: LiveData<MutableList<Item>> = _filterGoldList

    private val _filterSilverList = MutableLiveData<MutableList<Item>>()
    val filterSilverList: LiveData<MutableList<Item>> = _filterSilverList

    suspend fun myFilter(myList: MutableList<Item>, type: String) = withContext(Dispatchers.IO) {
        // 执行后台过滤,转为MutableList
        val filteredList = myList.filter { it.isMainPageItem == true }.toMutableList()
        // 根据类型更新对应LiveData
        when(type.lowercase()) {
            "gold" -> _filterGoldList.postValue(filteredList)
            "silver" -> _filterSilverList.postValue(filteredList)
        }
    }
}

步骤2:在Fragment中观察LiveData并管理子Adapter

在Fragment中持有子Adapter的引用,通过viewLifecycleOwner安全观察LiveData,数据变化时直接更新子Adapter:

class MainFragment : Fragment() {
    private lateinit var mainFragmentViewModel: MainFragmentViewModel
    // 持有子Adapter引用,避免重复创建
    private lateinit var goldAdapter: GoldAdapter
    private lateinit var silverAdapter: SilverAdapter

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mainFragmentViewModel = ViewModelProvider(this)[MainFragmentViewModel::class.java]

        // 初始化子Adapter
        goldAdapter = GoldAdapter()
        silverAdapter = SilverAdapter()

        // 初始化主Adapter,传入子Adapter引用
        val mainAdapter = MainFragmentAdapter(goldAdapter, silverAdapter, mRate, requireContext())
        mainRecyclerView.adapter = mainAdapter

        // 观察黄金过滤列表
        mainFragmentViewModel.filterGoldList.observe(viewLifecycleOwner) { filteredGold ->
            if (filteredGold.isNotEmpty()) {
                goldAdapter.goldList = filteredGold
                goldAdapter.notifyDataSetChanged()
            }
        }

        // 观察白银过滤列表(同理)
        mainFragmentViewModel.filterSilverList.observe(viewLifecycleOwner) { filteredSilver ->
            if (filteredSilver.isNotEmpty()) {
                silverAdapter.silverList = filteredSilver
                silverAdapter.notifyDataSetChanged()
            }
        }

        // 触发后台过滤
        mainFragmentViewModel.viewModelScope.launch {
            mainFragmentViewModel.myFilter(parentGoldList, "gold")
            mainFragmentViewModel.myFilter(parentSilverList, "silver")
        }
    }
}

步骤3:重构主Adapter,复用子Adapter实例

修改主Adapter的构造函数,传入已初始化的子Adapter,避免在onBindViewHolder中重复创建:

class MainFragmentAdapter(
    private val goldAdapter: GoldAdapter,
    private val silverAdapter: SilverAdapter,
    private val mRate: List<Rate>,
    private val myContext: Context
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (position) {
            1 -> {
                holder.itemView.diamond_text.text = "Gold"
                // 复用已有的goldAdapter
                holder.itemView.diamond_recycler.apply {
                    setHasFixedSize(true)
                    adapter = goldAdapter
                }
                // 设置费率数据
                if (mRate.isNotEmpty()) {
                    goldAdapter.goldRate = mRate[0].value!!
                }
                holder.itemView.view_more_button.setOnClickListener {
                    methodCallBack.click(gold)
                }
                goldAdapter.setListener(myContext)
            }
            // 处理白银类型的item(同理复用silverAdapter)
            2 -> {
                // ...
            }
        }
    }

    // 其他必要方法(getItemCount、onCreateViewHolder等)
}

核心逻辑说明

  1. 职责分离:Fragment负责数据观察与Adapter管理,Adapter仅做数据-视图绑定,符合单一职责原则。
  2. 生命周期安全:使用viewLifecycleOwner观察LiveData,确保Fragment销毁时自动取消观察,避免内存泄漏。
  3. 性能优化:复用子Adapter实例,避免在onBindViewHolder中重复创建对象,减少性能开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 17:35:16