【问题标题】:Performance issues with saving and loading data from RecyclerView using Moshi使用 Moshi 从 RecyclerView 保存和加载数据的性能问题
【发布时间】:2021-10-13 14:42:58
【问题描述】:

在我的 Android 应用程序的Fragment 中,我使用SharedPreferencesMoshi 来保存和加载我从RecyclerView 获得的数据。

这是我为该任务准备的两个功能:

private fun saveData() {
    val sharedPreferences = this@Main.requireContext().getSharedPreferences("recycler_view", Context.MODE_PRIVATE)
    val editor = sharedPreferences.edit()
    val moshi = Moshi.Builder().add(BigDecimalAdapter).add(KotlinJsonAdapterFactory()).build()
    val listMyData = Types.newParameterizedType(List::class.java, CardItem::class.java)
    val jsonAdapter : JsonAdapter<ArrayList<CardItem>> = moshi.adapter(listMyData)
    val json = jsonAdapter.toJson(dataList)
    editor.putString("data_list", json)
    editor.apply()
}

private fun loadData() {
    val sharedPreferences = this@Main.requireContext().getSharedPreferences("recycler_view", Context.MODE_PRIVATE)
    val json = sharedPreferences.getString("data_list", null)
    val type : Type = object : TypeToken<List<CardItem>>() {}.type
    val moshi = Moshi.Builder().add(BigDecimalAdapter).add(KotlinJsonAdapterFactory()).build()
    val jsonAdapter : JsonAdapter<ArrayList<CardItem>> = moshi.adapter(type)
    dataList = jsonAdapter.fromJson(json!!)!!
    if (dataList == null) {
        dataList = arrayListOf<CardItem>()
    }
}

在我的onViewCreated 中,我有这个用于调用loadData() 函数并构建RecyclerView

loadData()

recyclerView = rootView.findViewById(R.id.main_recycler_view)
recyclerView.setHasFixedSize(true)
recyclerViewLayoutManager = LinearLayoutManager(this@Main.requireContext())
adapter = MainAdapter(dataList, this)
recyclerView.layoutManager = recyclerViewLayoutManager
recyclerView.adapter = adapter

一切都按我的意愿进行,但是,当我转到这个特定片段时,我注意到延迟/滞后。我的应用程序中总共有三个片段,另外两个工作顺利,没有延迟/滞后,但是当我单击按钮转到该片段或滑动屏幕转到该片段时,切换有延迟.我该怎么做才能使Moshi 的性能更好?在保存和加载RecyclerView 数据时,我可以在代码中添加或修改什么以提高性能吗?

【问题讨论】:

  • 这是仅在第一个片段加载时的第一个应用启动时发生,还是每次在该片段上发生?
  • @PabloBaxter 仅在加载 RecyclerView 数据的第三个片段上以及每次加载该片段时。
  • 我会添加一些日志来跟踪导致问题的调用。我有一种预感,这是您共享的首选项,尤其是如果这可能是它的第一次加载。通常,您希望在类初始化时获取共享首选项对象。

标签: android kotlin android-recyclerview sharedpreferences moshi


【解决方案1】:

这似乎是应用程序可能在其主线程上做太多工作问题。 Json 解析是 CPU 密集型任务,并且鉴于您正在解析对象列表,这可能需要一些时间来执行,这会导致观察到的延迟,因为您正在 UI 线程上进行大量处理,因此无法绘制 UI。您可以使用 logcat 验证这一点,必须有一个类似 I/Choreographer: Skipped n frames : The application may be doing too much work on its main thread. 的条目

那么如何解决这个问题?

不要在 UI 线程上做太多工作,改用Coroutines

UI线程应该只用于更新UI,比如textView.text = "someText"等。当你需要执行长时间运行的任务时,你需要使用一些后台线程,这在kotlin中很简单,你可以让你的函数使用协程。

private fun loadData() = lifecycleScope.launch(Dispatchers.Default){
val sharedPreferences = this@Main.requireContext().getSharedPreferences("recycler_view", Context.MODE_PRIVATE)
   ...    
}

lifecycleScope.launch(Dispatchers.Default) 这将创建一个新的协程,它在后台线程而不是 UI 上执行您的代码。你也可以用类似的方式更新你的saveData函数。

除了 UI 线程问题,您的代码中还有一个设计问题。每次加载片段时您都在进行 JSON 解析,这不是非常理想的。相反,您应该只执行一次解析并将结果存储在database 中,然后您可以简单地从数据库中加载数据,而无需每次都执行解析。

【讨论】:

  • 由于我的代码在一个片段中,我将在哪里对从我的数据库获得的结果进行解析?例如,onResumeonViewCreated 等。我使用 Firebase 实时数据库来存储 JSON 字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多