如何解决Android Kotlin 协程在使用变量打开的片段上创建 RecyclerView
这是一个没有变量的工作版本:
片段:
viewmodel.lists.observe(viewLifecycleOwner) {
listadapter.submitList(it)
}
ViewHolder:
val lists = shishaDao.getList(HARDCODED_INT).asLiveData()
如您所见,有一个硬编码的整数。这个整数可以保存不同的值,这会改变列表的值。
这是我对变量的尝试:
片段:
viewmodel.lists(title).observe(viewLifecycleOwner) {
listadapter.submitList(it)
}
我现在想访问一个需要必要变量的函数,而不是访问视图持有者的变量。
ViewHolder:
fun lists(title: String): LiveData<List<Tabak>> {
val nr = dao.getNr(title)
return dao.getList(nr).asLiveData()
}
应用程序崩溃并出现以下错误:
Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
这里也有尝试过的方法:
fun lists(title: String): LiveData<List<Tabak>> {
val nr: Int = 0
viewmodelScope.launch {
nr = dao.getNr(title)
Log.e("NR",nr.toString())
}
return dao.getList(nr).asLiveData()
}
fun lists(title: String): LiveData<List<Tabak>> {
val nr: mutablelivedata<Int> = mutablelivedata(0)
viewmodelScope.launch {
nr.value = dao.getNr(title)
Log.e("NR",nr.value.toString())
}
return dao.getList(nr.value!!).asLiveData()
}
两种方法都不会崩溃。 Log.e 显示正确的数字,但最后一行仍然使用 0。
我的实际问题:如何从 dao.getNr(title) 获取 nr 值以在最后一行 getList(nr) 中使用它?
解决方法
我找到了一种使用 LiveData 的方法。这是一个很大的方法,但也很有用。
新 PreferenceManager.kt
class PreferencesManager @Inject constructor(context: Context) {
private val dataStore = context.createDataStore("user_preferences")
val preferencesFlow = dataStore.data
.catch { exception ->
if (exception is IOException) {
Log.e(TAG,"Error reading preferences",exception)
emit(emptyPreferences())
} else {
throw exception
}
}
.map { preferences ->
val choseMarke = preferences[PreferencesKeys.CHOSE_TITLE] ?: 2
FilterPreference(choseTitle)
}
suspend fun updateChoseTitle (choseTitle: Int) {
dataStore.edit { preferences ->
preferences[PreferencesKeys.CHOSE_TITLE] = choseTitle
}
}
private object PreferencesKeys {
val CHOSE_TITLE = preferencesKey<Int>("chosen_title")
}
}
Fragment.kt 看起来像这样
viewModel.lists.observe(viewLifecycleOwner) {
listAdapter.submitList(it)
}
和 ViewModel.kt
class ListsViewModel @ViewModelInject constructor(private val dao: Dao,private val preferencesManager: PreferencesManager,@Assisted private val state: SavedStateHandle) : ViewModel() {
val searchQuery = state.getLiveData("searchTitle","")
val preferencesFlow = preferencesManager.preferencesFlow
...
private val listsFlow = combine(searchQuery.asFlow(),preferencesFlow) { query,filterPreference ->
Pair(query,filterPreference)
}.flatMapLatest { (_,filterPreference) ->
dao.getList(filterPreference.choseMarke)
}
我不再尝试使用片段内的标题。在打开片段之前,我需要按下这个标题的按钮,然后我已经将标题(作为来自 dao getNr 的 int)保存在 mainActivity 中。
MainActivity.kt
onNavigationItemSelected(item: MenuItem): Boolean {
viewModel.onNavigationClicked(item)
}
MainViewModel.kt
fun onNavigationClicked(item: MenuItem) = viewModelScope.launch {
val choseMarkeNr = shishaDao.getMarkeNr(item.title.toString())
preferencesManager.updateChoseMarke(choseMarkeNr)
}
这种方式奏效了。 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。