使用 savestate 保存 recyclerview 项目
Posted
技术标签:
【中文标题】使用 savestate 保存 recyclerview 项目【英文标题】:Saving recyclerview items with savestate 【发布时间】:2021-10-27 05:55:20 【问题描述】:我目前正在编写一个显示电影列表的应用程序。该应用有 8 个片段包含回收视图:热门电影、动作片、喜剧片、恐怖片、浪漫片、科幻片、搜索和收藏夹。
recyclerview 中的项目包含一个复选框,用于将电影添加到收藏夹。当我滚动或退出应用程序时,复选框状态会重置。我正在尝试使用 savestate 保存复选框的状态,但它不起作用。
谁能告诉我我做错了什么?下面是视图模型。
谢谢。
MoviesListViewModel.kt
package com.example.moviesapp.ui
import androidx.lifecycle.*
import com.example.moviesapp.network.MoviesRepository
import com.example.moviesapp.network.MoviesResults
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
const val DEFAULT_QUERY = " "
const val ACTION_MOVIES = "moviesAction"
const val COMEDY_MOVIES = "moviesComedy"
const val HORROR_MOVIES = "moviesHorror"
const val ROMANCE_MOVIES = "moviesRomance"
const val SCIFI_MOVIES = "moviesScifi"
const val TRENDING_MOVIES = "moviesTrending"
enum class MovieApiStatus LOADING, ERROR, DONE
@HiltViewModel
class MoviesListViewModel @Inject constructor(
private val repository: MoviesRepository,
private var state: SavedStateHandle
): ViewModel()
private val _moviesAction: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(ACTION_MOVIES)
val moviesAction: LiveData<List<MoviesResults.Movies>> = _moviesAction
private val _moviesComedy: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(COMEDY_MOVIES)
val moviesComedy: LiveData<List<MoviesResults.Movies>> = _moviesComedy
private val _moviesHorror: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(HORROR_MOVIES)
val moviesHorror: LiveData<List<MoviesResults.Movies>> = _moviesHorror
private val _moviesRomance: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(
ROMANCE_MOVIES)
val moviesRomance: LiveData<List<MoviesResults.Movies>> = _moviesRomance
private val _moviesScifi: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(SCIFI_MOVIES)
val moviesScifi: LiveData<List<MoviesResults.Movies>> = _moviesScifi
private val _moviesTrending: MutableLiveData<List<MoviesResults.Movies>> = state.getLiveData(TRENDING_MOVIES)
val moviesTrending: LiveData<List<MoviesResults.Movies>> = _moviesTrending
private val _networkState = MutableLiveData<MovieApiStatus>()
val networkState: LiveData<MovieApiStatus> = _networkState
init
getMovies()
fun getAction()
viewModelScope.launch
_moviesAction.value = repository.getActionMovies()
fun getComedy()
viewModelScope.launch
_moviesComedy.value = repository.getComedyMovies()
fun getHorror()
viewModelScope.launch
_moviesHorror.value = repository.getHorrorMovies()
fun getRomance()
viewModelScope.launch
_moviesRomance.value = repository.getRomanceMovies()
fun getScifi()
viewModelScope.launch
_moviesScifi.value = repository.getScifiMovies()
fun getTrending()
viewModelScope.launch
_moviesTrending.value = repository.getTrendingMovies()
private var currentQuery = MutableLiveData(DEFAULT_QUERY)
val movies = currentQuery.switchMap
queryString ->
liveData
emit(repository.getSearchResults(queryString))
fun searchMovies(query: String)
currentQuery.value = query
private fun getMovies()
viewModelScope. launch
_networkState.value = MovieApiStatus.LOADING
try
_networkState.value = MovieApiStatus.DONE
catch (e: Exception)
_networkState.value = MovieApiStatus.ERROR
class MoviesListViewModelFactory @Inject constructor(private val repository: MoviesRepository, private val state: SavedStateHandle): ViewModelProvider.Factory
override fun <T : ViewModel?> create(modelClass: Class<T>): T
if (modelClass.isAssignableFrom(MoviesListViewModel::class.java))
@Suppress("UNCHECKED_CAST")
return MoviesListViewModel(repository, state) as T
throw IllegalArgumentException("Unknown ViewModel class")
【问题讨论】:
您应该存储在SharedPreferences
或类似DataStore 等的类似文件中,因为saveState
仅在活动停止或销毁之前有效
当您退出应用程序时,在 saveState 中保存不会保留数据。保存状态的数据仅在活动旋转或应用程序在后台时才会保留。
SharedPreferences 现已弃用。那我应该用什么?
【参考方案1】:
用于访问和修改 Context.getSharedPreferences(String, int) 返回的首选项数据的接口。对于任何特定的首选项集,所有客户端都共享一个此类的单个实例。对首选项的修改必须通过 Editor 对象,以确保首选项值保持一致状态并控制何时提交到存储。从各种 get 方法返回的对象必须被应用程序视为不可变对象。
注意:这个类提供了强大的一致性保证。它正在使用可能会降低应用程序速度的昂贵操作。频繁更改的属性或可以容忍损失的属性应使用其他机制。有关详细信息,请阅读 Editor.commit() 和 Editor.apply() 上的 cmets。
注意:该类不支持跨多个进程使用。
在您的情况下,您可以简单地存储键值对来记录相关选择。
【讨论】:
共享偏好已被弃用 JetpackDataStore
是一个不错的选择
我尝试使用 jetpack 数据存储保存复选框的状态,但我无法访问该复选框,因为该复选框位于布局内,并且该布局用于 recyclerview。以上是关于使用 savestate 保存 recyclerview 项目的主要内容,如果未能解决你的问题,请参考以下文章
Qt - Pyside - .saveGeom() .saveState() (再次)
在 JSF 中,“saveState()”方法被调用了两次。为啥?