You need to enable JavaScript to run this app. 使用Moshi存取RecyclerView数据时Fragment切换卡顿如何优化?
优惠活动
大模型
产品
解决方案
定价
更多

使用Moshi存取RecyclerView数据时Fragment切换卡顿如何优化?

性能优化方案

1. 核心卡顿原因定位

当前代码将磁盘IO(SharedPreferences读取)、JSON反序列化两个耗时操作全部放在主线程执行,Fragment切换时主线程需要负责UI渲染,耗时操作会阻塞主线程导致卡顿。

2. 代码优化方案

2.1 复用Moshi实例与JsonAdapter

当前每次调用save/load方法都会重复构建Moshi实例、反射生成JsonAdapter,这两个对象可以全局复用,避免重复的反射解析开销:

// 提为Fragment成员变量,懒加载仅初始化一次
private val sharedPreferences by lazy {
    requireContext().getSharedPreferences("recycler_view", Context.MODE_PRIVATE)
}
private val moshi by lazy {
    Moshi.Builder()
        .add(BigDecimalAdapter)
        .add(KotlinJsonAdapterFactory())
        .build()
}
private val cardListJsonAdapter by lazy {
    val listType = Types.newParameterizedType(List::class.java, CardItem::class.java)
    moshi.adapter<ArrayList<CardItem>>(listType)
}

2.2 异步执行数据存取操作

将耗时的IO、序列化/反序列化操作放到后台线程执行,避免阻塞主线程,推荐使用Android官方协程实现:

// 异步加载数据
private fun loadDataAsync() = lifecycleScope.launch(Dispatchers.IO) {
    val json = sharedPreferences.getString("data_list", null)
    val loadedData = json?.let { cardListJsonAdapter.fromJson(it) } ?: arrayListOf()
    // 切回主线程更新UI
    withContext(Dispatchers.Main) {
        dataList = loadedData
        adapter.updateData(loadedData) // 自行在Adapter中实现updateData方法更新列表
    }
}

// 异步保存数据
private fun saveDataAsync() = lifecycleScope.launch(Dispatchers.IO) {
    val json = cardListJsonAdapter.toJson(dataList)
    sharedPreferences.edit()
        .putString("data_list", json)
        .apply()
}

2.3 调整RecyclerView初始化顺序

不需要等待数据加载完成再初始化RecyclerView,先初始化UI组件,数据加载完成后再更新Adapter即可:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // 先初始化RecyclerView
    recyclerView = rootView.findViewById(R.id.main_recycler_view)
    recyclerView.setHasFixedSize(true)
    recyclerView.layoutManager = LinearLayoutManager(requireContext())
    adapter = MainAdapter(arrayListOf(), this)
    recyclerView.adapter = adapter

    // 异步加载数据,加载完成后更新Adapter
    loadDataAsync()
}

3. 进阶优化方案

  • 给CardItem类添加@JsonClass(generateAdapter = true)注解,开启Moshi代码生成能力,无需反射即可生成适配器,反序列化性能可提升30%以上,同时可以移除KotlinJsonAdapterFactory依赖。
  • 引入ViewModel缓存加载完成的列表数据,Fragment因切换销毁重建时,直接从ViewModel取缓存数据,无需重复执行SP读取和反序列化操作。
  • 若数据量超过百条级别,建议替换SharedPreferences为Jetpack DataStore或Room数据库,SharedPreferences本身不适合存储大体积JSON字符串,读写性能远低于专门的存储组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 07:27:02