RecyclerView,带有 DiffUtil 和 LiveData
RecyclerView, with DiffUtil and LiveData
我已经坚持了几天,真的需要一些帮助和理解如何使用 DiffUtil 设置 RecylerView(RV),似乎无论我尝试什么我都无法让 RV 更新。我会 运行 了解我所拥有的,希望有人能指出我做错了什么。
应用启动
- 创建视图模型,
- 然后在 ViewModel 中填充 LiveDataList。
- RV实例化
- RV应用LayoutManager和ListAdapter
- ItemTouchHelper 附加到 RecyclerView,允许在向左滑动时从 LiveDataList 中删除项目。
- 观察LiveDataList,我的理解是当列表发生变化时,如果原始提交的列表与修改后的列表有差异,观察者会将列表提交给AdapterList与旧列表进行比较列出 AdapterList 将更新 RecyclerView。
为什么在 LiveDataList 列表中添加或删除项目时不调用观察者进行更新。
class MainActivity : AppCompatActivity() {
var myAdapter = RVAdapter()
private lateinit var viewModel: MyViewModel()
override fun onCreateView(savedInstanceState: Bundle? ) {
super.onCreate(savedInstanceState)
// Initialize the ViewModel, that stores the userList.
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
// Creates list of users
addUser()
// Link an RV object to view
val rv = findViewById<RecyclerView>(R.id.recycler_view)
// apply RV Settings.
rv.apply {
layoutManager = LinearLayoutManager(baseContext, LinearLayoutManager.VERTICAL, false)
adapter= myAdapter
}
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
override fun onMove(...) {
// move items isn't used.
}
override fun onSwipe(viewHolder: ViewHolder, direction: Int) {
// When I swipe a second item, the app crashes.
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
editList?.removeAt(viewHolder.adapterPosition)
viewModel.usersList?.postValue(userList)
}
}).attachtoRecyclerView(rv)
// The observer will run after swiping an item but the UI doesn't update.
viewModel.usersList?observe(this, Observer {
it?.let {
// Should update list but it doesn't
myAdapter.submitList(it)
}
}
private fun addUser() {
// Shouldn't there be away to add Items directly to list in ViewModel.
val newList: MutableList<User> = mutableListOf()
newList.add(User("Shawn", 1)
newList.add(User("Shannon", 2)
newList.add(User("Don", 3)
viewModel.userList?.postValue(newList)
}
数据class:这是非常基本的,这里发生的事情不多。
data class User(val name: String, val accountNumber: Int) {
}
ViewModel:MyViewModel 仅存储 MutableLiveDat
class MyViewModel : ViewModel() {
val usersList: MutableLiveData<List<User>>? = MutableLiveData()
}
RecycleView 适配器
class RVAdapter : ListAdapter<User, RVAdapter.ViewHolder>(MyDiffCallback() {
// This DiffUtil class never gets called not even on startup.
class MyDiffCallback: DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.name == newItem.name
}
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
... Rest of RV is working fine but can be included if it's helpful.
}
当从 LiveData List 中删除或添加项目时,观察者将修改后的列表传递给 ListAdapter 可以做什么?
包括 StackTrace
索引出站。
2020-10-05 20:14:16.538 19042-19042/com.example.practicerecyclerview2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.practicerecyclerview2, PID: 19042
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.remove(ArrayList.java:503)
at com.example.practicerecyclerview2.MainActivity$onCreate.onSwiped(MainActivity.kt:100)
at androidx.recyclerview.widget.ItemTouchHelper.run(ItemTouchHelper.java:712)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
您的 ListAdapter
没有更新的原因是它无法在您提交的列表中找到差异,因为您已经对其进行了修改。这样 notifyDataChanged()
方法就不会被调用,您会在第二次滑动时得到 IndexOutOfBoundsException
,因为该项目不再存在。
解决方法是修改并提交一份副本的列表:
override fun onSwipe(viewHolder: ViewHolder, direction: Int) {
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
val editListCopy = editList?.toMutableList()
editListCopy?.removeAt(viewHolder.adapterPosition)
viewModel.users?.postValue(editListCopy)
}
我已经坚持了几天,真的需要一些帮助和理解如何使用 DiffUtil 设置 RecylerView(RV),似乎无论我尝试什么我都无法让 RV 更新。我会 运行 了解我所拥有的,希望有人能指出我做错了什么。
应用启动
- 创建视图模型,
- 然后在 ViewModel 中填充 LiveDataList。
- RV实例化
- RV应用LayoutManager和ListAdapter
- ItemTouchHelper 附加到 RecyclerView,允许在向左滑动时从 LiveDataList 中删除项目。
- 观察LiveDataList,我的理解是当列表发生变化时,如果原始提交的列表与修改后的列表有差异,观察者会将列表提交给AdapterList与旧列表进行比较列出 AdapterList 将更新 RecyclerView。
为什么在 LiveDataList 列表中添加或删除项目时不调用观察者进行更新。
class MainActivity : AppCompatActivity() {
var myAdapter = RVAdapter()
private lateinit var viewModel: MyViewModel()
override fun onCreateView(savedInstanceState: Bundle? ) {
super.onCreate(savedInstanceState)
// Initialize the ViewModel, that stores the userList.
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
// Creates list of users
addUser()
// Link an RV object to view
val rv = findViewById<RecyclerView>(R.id.recycler_view)
// apply RV Settings.
rv.apply {
layoutManager = LinearLayoutManager(baseContext, LinearLayoutManager.VERTICAL, false)
adapter= myAdapter
}
ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
override fun onMove(...) {
// move items isn't used.
}
override fun onSwipe(viewHolder: ViewHolder, direction: Int) {
// When I swipe a second item, the app crashes.
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
editList?.removeAt(viewHolder.adapterPosition)
viewModel.usersList?.postValue(userList)
}
}).attachtoRecyclerView(rv)
// The observer will run after swiping an item but the UI doesn't update.
viewModel.usersList?observe(this, Observer {
it?.let {
// Should update list but it doesn't
myAdapter.submitList(it)
}
}
private fun addUser() {
// Shouldn't there be away to add Items directly to list in ViewModel.
val newList: MutableList<User> = mutableListOf()
newList.add(User("Shawn", 1)
newList.add(User("Shannon", 2)
newList.add(User("Don", 3)
viewModel.userList?.postValue(newList)
}
数据class:这是非常基本的,这里发生的事情不多。
data class User(val name: String, val accountNumber: Int) {
}
ViewModel:MyViewModel 仅存储 MutableLiveDat
class MyViewModel : ViewModel() {
val usersList: MutableLiveData<List<User>>? = MutableLiveData()
}
RecycleView 适配器
class RVAdapter : ListAdapter<User, RVAdapter.ViewHolder>(MyDiffCallback() {
// This DiffUtil class never gets called not even on startup.
class MyDiffCallback: DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem.name == newItem.name
}
override fun areContentsTheSame(oldItem: User, newItem: User): Boolean {
return oldItem == newItem
}
}
... Rest of RV is working fine but can be included if it's helpful.
}
当从 LiveData List 中删除或添加项目时,观察者将修改后的列表传递给 ListAdapter 可以做什么?
包括 StackTrace 索引出站。
2020-10-05 20:14:16.538 19042-19042/com.example.practicerecyclerview2 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.practicerecyclerview2, PID: 19042
java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.remove(ArrayList.java:503)
at com.example.practicerecyclerview2.MainActivity$onCreate.onSwiped(MainActivity.kt:100)
at androidx.recyclerview.widget.ItemTouchHelper.run(ItemTouchHelper.java:712)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
您的 ListAdapter
没有更新的原因是它无法在您提交的列表中找到差异,因为您已经对其进行了修改。这样 notifyDataChanged()
方法就不会被调用,您会在第二次滑动时得到 IndexOutOfBoundsException
,因为该项目不再存在。
解决方法是修改并提交一份副本的列表:
override fun onSwipe(viewHolder: ViewHolder, direction: Int) {
val editList: MutableList<User>? = viewModel.usersList?.value as MutableList<User>?
val editListCopy = editList?.toMutableList()
editListCopy?.removeAt(viewHolder.adapterPosition)
viewModel.users?.postValue(editListCopy)
}