使用Moshi从RecyclerView保存和加载数据时的性能问题



在我的Fragment为我的Android应用程序,我使用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

一切都如我所愿,然而,当我去到这个特定的片段时,我注意到延迟/滞后。在我的应用中总共有3个片段,另外两个可以顺利运行,没有延迟/滞后,但是当我点击按钮进入这个片段或滑动屏幕进入这个片段时,切换就会有延迟。我怎么做才能使Moshi的性能更好?有什么我可以添加到我的代码或修改,使性能更好时保存和加载RecyclerView数据?

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

的条目。那么如何解决这个问题呢?

不要在UI线程上做太多的工作,使用协程代替

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解析,这不是很理想。相反,您应该只执行一次解析并将结果存储在数据库中,然后您可以简单地从数据库加载数据,而无需每次都执行解析。

最新更新