簡體   English   中英

RecyclerView,帶有 DiffUtil 和 LiveData

[英]RecyclerView, with DiffUtil and LiveData

我已經堅持了幾天,並且可以真正使用一些關於如何使用 DiffUtil 設置 RecylerView(RV) 的幫助和理解,似乎無論我嘗試什么我都無法讓 RV 更新。 我將遍歷我所擁有的,希望有人能闡明我做錯了什么。

應用啟動

  • 創建視圖模型,
    • LiveDataList 然后被填充到 ViewModel 中。
  • RV 已實例化
    • LayoutManager 和 ListAdapter 應用於 RV。
  • ItemTouchHelper 附加到 RecyclerView 允許在向左滑動時從 LiveDataList 中刪除項目。
  • 觀察LiveDataList,我的理解是當列表發生變化時,觀察者將列表提交給AdapterList,如果原始提交的列表與修改后的列表有差異,則AdapterList將更新列表與舊列表進行比較回收器視圖。

為什么在 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 只存儲 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 列表中刪除或添加一個項目時,觀察者將修改后的列表傳遞給 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$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)

您的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)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM