当前位置: 首页 > 知识库问答 >
问题:

回收人员视图,与DiffUtil和LiveData

魏高邈
2023-03-14

我已经被困在这个问题上几天了,真的需要一些帮助和理解如何用DiffUtil设置RecylerView(RV),似乎无论我尝试什么,我都无法让RV更新。我会浏览我所拥有的,希望有人能解释一下我做错了什么。

应用程序启动

  • 创建视图模型,
    • 然后在ViewModel中填充LiveDataList。
    • LayoutManager和ListAdapter应用于RV

    为什么在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)
    }
    
    

    数据类:这是非常基本的,在这里很少发生。

    data class User(val name: String, val accountNumber: Int) {
    }
    

    ViewModel:MyViewModel只存储可变的LiveDat

    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列表中删除或添加,观察者将把修改后的列表传递给列表适配器时,可以做些什么?

    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$2.onSwiped(MainActivity.kt:100)
            at androidx.recyclerview.widget.ItemTouchHelper$4.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)
    

共有1个答案

秦彦君
2023-03-14

您的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)
}
 类似资料:
  • 是否可以将可展开的列表项与新的 RecyclerView 一起使用?喜欢 ExpandableListView?

  • 我有一个像相册这样的项目列表,我通过RecyclerView显示它。 此外,每个项目都有一个按钮,通过单击该按钮可以向服务器发送一些数据,然后滚动到列表中的下一个位置。 所以我的问题是: 如果调用了smoothScrollToPosition()方法,如何防止RecyclerView手动滚动(手势),但滚动到某个位置?

  • 我已经在我的应用程序中成功实现了RecyclerView。RecyclerView有三项,即标题(TextView)、图像按钮和描述(TextView)。 标题和图像按钮始终可见,而通过单击图像按钮切换描述的可见性(默认设置为“已消失”)。 我遇到的问题是,当您单击一个项目中的ImageButton并且描述变得可见时,当您向下滚动或向上滚动时,即使我没有单击ImageButton以使其可见,第五个

  • 这是我的应用,问题出在哪里 我希望我的物品能像这个应用一样合身 我正在使用带有的。我的问题是,当其中一个项目具有更长的文本时,您可以在图像中看到网格项的高度不相同。我正在从Firebase加载数据,并在列表具有数据时通知。我尝试了一切,但找不到一个解决方案来自动适应项目,如第二张图片所附。有什么帮助吗? 这是我的recyclerview项目布局

  • 如何从XML设置RecyclView layoutManager?

  • 我以以下方式使用来显示在SQLite DB中更新的位置项列表。 这些项目被很好地删除,并在我滑动它们时更新。但是当我滑动删除最后一个项目时,它又出现在视图中。当我关闭应用程序并重新打开应用程序时,该项目已被删除。 但当项目被滑动以删除时,在该应用程序运行的实例中,即使滑动多次,该项目也不会从视图中删除。 refreshPlacesData() 我错过了什么吗?谢谢。 编辑:我尝试更新适配器而不是m