如何解决使用MVVM viewmodel和livedata时,如何在更改配置后保留RecyclerView的滚动位置?
先阅读: 抱歉,看来我玩了。我以前在xml中使用RecyclerView,但将其切换为CardStackView(它仍然使用完全相同的RecyclerView适配器)。如果我切换回RecyclerView,则下面的原始代码可以正常工作-滚动位置会在配置更改时自动保存和恢复。
我正在使用MVVM viewmodel类,该类在配置更改后成功为RecyclerView保留了列表数据。但是,以前的RecyclerView位置不会恢复。这是预期的行为吗?什么是解决此问题的好方法?
我看到blog post on medium简短地提到您可以通过在设置RecyclerView上的适配器数据之前设置适配器数据来保留滚动位置。 据我了解,配置更改后,先前观察到的实时数据将得到回调。该回调是我设置适配器数据的地方。但是似乎此回调发生在onCreate()函数完成后,此时我的RecyclerView适配器已经设置。
class MainActivity : AppCompatActivity() {
private val adapter = MovieAdapter()
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Create or retrieve viewmodel and observe data needed for recyclerview
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
viewModel.movies.observe(this,{
adapter.items = it
})
binding.recyclerview.adapter = adapter
// If viewmodel has no data for recyclerview,retrieve it
if (viewModel.movies.value == null) viewModel.retrieveMovies()
}
}
class MovieAdapter :
RecyclerView.Adapter<MovieAdapter.MovieViewHolder>() {
var items: List<Movie> by Delegates.observable(emptyList()) { _,_,_ ->
notifyDataSetChanged()
}
class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val binding = ItemMovieCardBinding.bind(itemView)
fun bind(item: Movie) {
with(binding) {
imagePoster.load(item.posterUrl)
textRating.text = item.rating.toString()
textDate.text = item.date
textOverview.text = item.overview
}
}
}
override fun onCreateViewHolder(parent: ViewGroup,viewType: Int): MovieViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_movie_card,parent,false)
return MovieViewHolder(view)
}
override fun onBindViewHolder(holder: MovieViewHolder,position: Int) {
holder.bind(items[position])
}
override fun getItemCount() = items.size
}
class MainViewModel : ViewModel() {
private val _movies = MutableLiveData<List<Movie>>()
val movies: LiveData<List<Movie>> get() = _movies
fun retrieveMovies() {
viewModelScope.launch {
val client = ApiClient.create()
val result: Movies = withContext(Dispatchers.IO) { client.getPopularMovies() }
_movies.value = result.movies
}
}
}
解决方法
仅在适配器的项目可用时设置适配器。
viewModel.movies.observe(this,{
adapter.items = it
binding.recyclerview.adapter = adapter
})
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。