RecycleView 列表动态刷新,页面不动,只刷新某个符合条件的item
有人用过 DiffUtil ,也可以,不过发现了SortedList 更好。写了一个测试
- SortedList是一个有序列表(数据集)的实现,可以保持ItemData都是有序的,并(自动)通知列表(RecyclerView)(数据集)中的更改。
data class TestListBean(
var index:Int,
var tag:String,
)
自定义一个SortedList
class SortListCallBack(adapter: TestSortedAdapter?):SortedListAdapterCallback<TestListBean>(adapter) {
override fun compare(o1: TestListBean?, o2: TestListBean?): Int {
o1 ?: return -1
o2 ?: return -2
return o1.index - o2.index
}
override fun areContentsTheSame(oldItem: TestListBean?, newItem: TestListBean?): Boolean {
if (oldItem?.index != newItem?.index){
return false
}
if (oldItem?.tag != newItem?.tag){
return false
}
return true
}
override fun areItemsTheSame(item1: TestListBean?, item2: TestListBean?): Boolean {
return item1?.index == item2?.index
}
override fun getChangePayload(item1: TestListBean?, item2: TestListBean?): Any? {
return super.getChangePayload(item1, item2)
}
}
适配器
class TestSortedAdapter:BaseQuickAdapter<TestListBean,BaseViewHolder>(R.layout.item_test_sort_layout) {
val mCallback =SortListCallBack(this)
val mSortedList = SortedList(TestListBean::class.java,SortedList.BatchedCallback(mCallback))
override fun onItemViewHolderCreated(viewHolder: BaseViewHolder, viewType: Int) {
super.onItemViewHolderCreated(viewHolder, viewType)
ItemTestSortLayoutBinding.bind(viewHolder.itemView)
}
override fun convert(holder: BaseViewHolder, item: TestListBean) {
holder.getBinding<ItemTestSortLayoutBinding>()?.run {
tvTagName.text = item.tag
}
}
fun setSortedList(list: MutableList<TestListBean>){
data.addAll(list)
mSortedList.addAll(list)
}
fun sorted():SortedList<TestListBean>{
return mSortedList
}
}
Activity
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
private val viewModel by viewModels<ListViewModel>()
private var adapter:TestSortedAdapter? = null
@SuppressLint("NotifyDataSetChanged")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel.listData.observe(this){
adapter?.setSortedList(it)
}
if (adapter == null){
adapter = TestSortedAdapter()
}
binding.recycleView.adapter = adapter
viewModel.initList()
binding.btnChange.setOnClickListener {
val index = (0..20).random()
WLog.e("btnChange","=====> 更新下标:$index")
val list = mutableListOf<TestListBean>()
adapter?.data?.let { it1 -> list.addAll(it1) }
val bean = list.find { it.index == index }
bean?.tag = "更新:$index"
adapter?.sorted()?.run {
beginBatchedUpdates()
clear()
adapter?.notifyDataSetChanged()
addAll(list)
endBatchedUpdates()
}
}
}
}
ListViewModel 只是一个初始化测试数据的。
当前几右下按钮时,随时的下标数据开始更新,页面直接更新对应的item 不会发生移动
下图,更新后的页面:
参考:IM会话列表刷新优化思考 https://juejin.cn/post/7183517773790707769