So I have a simple implementation to display a list of users in a RecyclerView
, and the list is queried in a ViewModel
as LiveData
.
The problem is that the UI is not updated to show the latest list - called users
- even when the list is observed. I just set up a list of demo users for now.
Here's my ViewModel:
class MainViewModel : ViewModel() {
private val demoData = listOf(
User(userName = "Bob", favoriteColor = "Green"),
User(userName = "Jim", favoriteColor = "Red"),
User(userName = "Park", favoriteColor = "Blue"),
User(userName = "Tom", favoriteColor = "Yellow"),
User(userName = "Lee", favoriteColor = "Black"),
User(userName = "Xiu", favoriteColor = "Gray")
)
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>>
get() = _users
init {
_users.value = listOf()
}
fun loadUsers() {
_users.value = demoData.toMutableList().apply { shuffle() }
}
}
And my ViewModel's attached Fragment:
// ...
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
viewModel.users.observe(this, Observer {
mAdapter.notifyDataSetChanged()
})
mAdapter = UsersAdapter(viewModel.users.value!!)
mainRV = view?.findViewById<RecyclerView>(R.id.rv_main)?.apply {
adapter = mAdapter
layoutManager = LinearLayoutManager(view?.context)
}
viewModel.loadUsers()
}
P.S. the UsersAdapter
is a usual RecyclerView.Adapter
.
I have made sure to call setValue
on my users list to call the Observer, thus I am not sure what is missing here. Is my adapter wrongly setup?
fun loadUsers() {
_users.value = demoData.toMutableList().apply { shuffle() }
}
toMutableList()
creates a new list with the data, see the source code:
public fun <T> Collection<T>.toMutableList(): MutableList<T> {
return ArrayList(this)
}
So instead of getting the initial value and never updating your adapter, you should update the list in the adapter and show that.
viewModel.users.observe(this, Observer { users ->
mAdapter.updateData(users)
})
Where if you are not using ListAdapter
, then you can define this method like this:
class MyAdapter: RecyclerView.Adapter<ViewHolder>(
private var list: List<User> = Collections.emptyList()
) {
...
fun updateData(users: List<User>) {
this.users = users
notifyDataSetChanged()
}
}
You can also use ListAdapter
and submitList
and you'll also get animations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With