DiffUtil问题:旧列表和新列表相同

时间:2019-06-07 09:58:59

标签: android kotlin android-recyclerview android-diffutils

上下文:
MainActivity启动,创建ItemObject的列表,然后调用ListFragment。当用户单击button(位于MainActivity中)时,它将修改列表,然后调用listFragment对其进行更新。

发现问题:
update的{​​{1}}函数中,listFragmentnewList相同。

这是我的代码。

oldList

MainActivity

还有class MainActivity : AppCompatActivity() { private val viewModel = MainViewModel() private var button : FloatingActionButton? = null private val listFragment = ListFragment.newInstance() var list = ArrayList<ItemObject>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) binding.viewModel = viewModel button = binding.button button?.setOnClickListener { modifyList() } createItemsList() } /** * This creates a list of 10 ItemObject, that will contains `i` as `randomInt` and "TEST $i" as `title`, then call * setListFragment(). */ private fun createItemsList() { val itemsList = ArrayList<ItemObject>() var i = 0 while (i < 10) { itemsList.add(ItemObject().apply { this.randomInt = i ; this.title = "TEST $i" }) i++ } list = itemsList setListFragment() } /** * Set listFragment inside content. */ private fun setListFragment() { supportFragmentManager.beginTransaction().replace(R.id.content, listFragment).commit() } /** * Triggered when the user clicks on the FloatingActionButton. Will modify each even item, add 2 to its `randomInt` * and set its `title` to "MODIFIED $randomInt". */ private fun modifyList() { list.forEach { if (it.randomInt % 2 == 0) { it.randomInt += 2 it.title = "MODIFIED ${it.randomInt}" } } if (listFragment.isAdded) { listFragment.updateList(list) } } inner class MainViewModel }

ListFragment

这是我的class ListFragment : Fragment() { private val viewModel = ListViewModel() private val listAdapter = ListAdapter() private var listRv : RecyclerView? = null private var list = ArrayList<ItemObject>() override fun onCreateView(inflater: LayoutInflater, parent: ViewGroup?, savedInstanceState: Bundle?): View? { val binding = DataBindingUtil.inflate<FragmentListBinding>(inflater, R.layout.fragment_list, parent, false) binding.viewModel = viewModel listRv = binding.listRv list = (activity as MainActivity).list setList() return (binding.root) } /** * Sets up the RecyclerView and set the list inside it. */ private fun setList() { listRv?.layoutManager = LinearLayoutManager(context) listRv?.adapter = listAdapter listRv?.post { listAdapter.setData(list) } } /** * Triggered by MainActivity when the user clicks on the button and the list is modified. Will call update() method * from adapter. */ fun updateList(newList : ArrayList<ItemObject>) { listAdapter.update(newList) } companion object { fun newInstance() : ListFragment = ListFragment() } inner class ListViewModel inner class ItemDiff : DiffUtil.Callback() { private var old = ArrayList<ItemObject>() private var new = ArrayList<ItemObject>() fun setLists(old : ArrayList<ItemObject>, new : ArrayList<ItemObject>) { this.old = old this.new = new } override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { println("ARE ITEMS ${old[oldItemPosition].title} THE SAME ? ${(old[oldItemPosition] == new[newItemPosition])}") return (old[oldItemPosition] == new[newItemPosition]) } override fun getOldListSize(): Int = old.size override fun getNewListSize(): Int = new.size override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { println("ARE ITEMS ${old[oldItemPosition].title} CONTENTS THE SAME ? ${(old[oldItemPosition].title == new[newItemPosition].title && old[oldItemPosition].randomInt == new[newItemPosition].randomInt)}") return (old[oldItemPosition].title == new[newItemPosition].title && old[oldItemPosition].randomInt == new[newItemPosition].randomInt) } override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? { val oldItem = old[oldItemPosition] val newItem = new[newItemPosition] val bundle = Bundle() if (oldItem.title != newItem.title) { println("SHOULD ADD NEW STRING ${newItem.title}") bundle.putString("title", newItem.title) } if (oldItem.randomInt != newItem.randomInt) { println("SHOULD ADD NEW INT ${newItem.randomInt}") bundle.putInt("randomInt", newItem.randomInt) } return (bundle) } } inner class ListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() { private var items = ArrayList<ItemObject>() fun setData(list : ArrayList<ItemObject>) { items = list notifyDataSetChanged() } /** * @param new * Triggered when the list is modified in the parent activity. Uses DiffUtil to update the list. */ fun update(new : ArrayList<ItemObject>) { println("///// IN UPDATE ; WILL PRINT OLD AND NEW LIST /////") items.forEach { println("OLD ITEM ${it.title}") } new.forEach { println("NEW ITEM ${it.title}") } println("///// PRINT END /////") val diffCallback = ItemDiff() diffCallback.setLists(old = items, new = new) val diffResult = DiffUtil.calculateDiff(diffCallback) diffResult.dispatchUpdatesTo(this) items = new } override fun onCreateViewHolder(parent: ViewGroup, position: Int): RecyclerView.ViewHolder { return (ItemViewHolder(DataBindingUtil.inflate<ItemBinding>(LayoutInflater.from(parent.context), R.layout.item, parent, false).apply { viewModel = ItemViewModel() })) } override fun getItemCount(): Int = items.size override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { (holder as ItemViewHolder).setData(items[position]) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) { println("IN ON BIND VIEWHOLDER ; PAYLOAD SIZE = ${payloads.size}") if (payloads.isEmpty()) super.onBindViewHolder(holder, position, payloads) else { val bundle = payloads[0] as Bundle if (bundle.size() != 0) { val name = bundle.getString("name") val randomInt = bundle.getInt("randomInt") if (name != null) (holder as ItemViewHolder).setName(name) (holder as ItemViewHolder).setRandomInt(randomInt) } } } inner class ItemViewHolder(private val binding : ItemBinding) : RecyclerView.ViewHolder(binding.root) { fun setData(item : ItemObject) { binding.viewModel?.setData(item) } fun setRandomInt(newInt : Int) { binding.viewModel?.setRandomInt(newInt) } fun setName(newName : String) { binding.viewModel?.setTitle(newName) } } inner class ItemViewModel { val title = ObservableField<String>("") val randomInt = ObservableField<String>("") fun setData(item : ItemObject) { setRandomInt(item.randomInt) setTitle(item.title) } fun setRandomInt(newInt : Int) { randomInt.set(newInt.toString()) } fun setTitle(newName : String) { title.set(newName) } } } } 课:

ItemObject

奇怪的是,我从不修改class ItemObject { var title = "" var randomInt = 0 } 中的列表。那么,当列表更新时,我的debug println怎么可能告诉我旧列表和新列表是相同的?

1 个答案:

答案 0 :(得分:0)

您可以尝试做:

fun setData(list : ArrayList<ItemObject>) {
            items.clear
            items.addAll(list)
            notifyDataSetChanged()
}