概述
SortedList继承于java.lang.Object
,是android.support.v7.util
包下的工具类。这个类,与java.util包下的ArrayList、List等类没有丝毫的关系,不管是继承还是实现。而,又与它们相像,在这个类的内部,封装了对一系列对数据的操作:插入,删除,移动,更新等。
SortedList实际上是一个排序列表的实现,提供处理了两种角色:
- 保持列表的顺序
- 分发列表更改的信息,以便绑定的RecyclerView.Adapter更新UI
也就是说,SortedList里面的数据集是按照指定的条件排序的,不需要再为排序而烦恼。而,和ArrayList、List等类的排序方式是一样的,它通过compare(Object,Object)方法对Item进行排序,这样又显得不陌生。对于Item的搜索,它采用的二进制搜索来检索Item,提高了检索的效率。
核心方法
添加
- add(T item):添加指定的item到SortedList中
- addAll(T… items):一次性添加多个items到SortedList中
- addAll(Collection items):将给定的集合添加到SortedList中
- addAll(T[] items,boolean mayModifyInput):添加给出的items到指定的list中,当mayModifyInput为true时,SortList在操作数据期间可能直接使用该数组的引用,以节省内存分配。此时,你不能够继续引用数组甚至是更改数组
删除
- clear():清空数据集
- remove(T item):删除指定的Item,然后调用onRemoved()方法
- removeItemAt(int index):删除指定索引的item,然后调用onRemoved()方法
更新
- updateItemsAt(int index,T item):更新指定索引的item,然后调用onChanged(int,int)方法,onMoved(int,int)方法
获取指定索引的Item
- get(int index)
获取Item的索引
- indexOf(T item)
事务
- beginBatchedUpdates():批量处理适配器更新操作发生在调用当前方法和调用endBatchedUpdates()之间
- endBatchedUpdates():结束更新事务,回调处理事件,和beginBatchedUpdates()一起使用
核心类
- SortedList.Callback:在该类中,定义了一系列的SortedList操作,包括如何排序以及处理重复的Item。同时,SortedList中数据发生更改时回调相应的方法。
- SortedList.BatchedCallback:它是SortedList.Callback的实现类,可以批量处理并SortedList分发的操作。比如,如果要将多个Item添加到SortedList,同时将Item添加到连续索引中,BatchedCallback将单个onInserted(index,1)调用转换为一个onInserted(index,N),这样可以使RecyclerView更轻松、高效的更新UI。
SortedListAdapterCallback:它是SortedListAdapterCallback的实现类,主要与RecyclerView.Apdater配合使用,在它内部定义了RecyclerView.Apdater,同时实现了数据集变化时的更新操作。此时,只需要实现以下3个方法即可:
- areItemsTheSame():用于判断两个Item是否相同
- areContentsTheSame():用于判断两个Item是否有相同的内容
- compare():排序条件
这里需要注意的是,BatchedCallback和SortedListAdapterCallback是不同的,尽管它们都是SortedList.Callback的实现类:
- 在创建SortedList.BatchedCallback实例时,必须传递SortedList.Callback示例,是为了将SortedList分发的操作分发给它。这个类的主要作用是用来批量处理SortedList分发的操作。但是,不管是对Item排序,还是处理相同的Item,甚至是执行SortedList分发的操作都是由传递过来的SortedList.Callback实现。
- SortedListAdapterCallback只是SortedListAdapterCallback的简单实现,当SortedList与RecyclerView.Apdater配合使用时,只是实现了Adapter更新UI的部分。
简单实现
SortedList基于维持列表中Item的顺序这一特性,在实际开发过程中,还是带来很多的遍历。比如,在查看成绩列表时,只需将成绩添加至列表即可,它会自动排序,我们不需要再考虑。下面就是SortedList的示例。
创建bean类
data class StudentBean(val no: Int, val name: String, val rank: Int)
创建SortedListAdapterCallback的实现类
class StudentCallback<R : RecyclerView.ViewHolder, T : RecyclerView.Adapter<R>>(@NonNull private val adapter: T) : SortedListAdapterCallback<StudentBean>(adapter) { // 默认按照学号排序 private var sortedType = SortedListActivity.SortedType.RANK // 判断两个Item是否相同 override fun areItemsTheSame(item1: StudentBean?, item2: StudentBean?): Boolean { return item1?.no == item2?.no } // 排序条件 override fun compare(o1: StudentBean?, o2: StudentBean?): Int { return when (sortedType) { SortedListActivity.SortedType.NO -> o1!!.no - o2!!.no SortedListActivity.SortedType.NO_REVERSE -> o2!!.no - o1!!.no SortedListActivity.SortedType.RANK -> o1!!.rank - o2!!.rank SortedListActivity.SortedType.RANK_REVERSE -> o2!!.rank - o1!!.rank } } // 判断两个Item的内容是否相同 override fun areContentsTheSame(oldItem: StudentBean?, newItem: StudentBean?): Boolean { return oldItem == newItem } // 设置排序类型 fun setType(type: SortedListActivity.SortedType) { this.sortedType = type } }
在StudentCallback这个实现类中,指定了按学号正序/逆序或者排名正序/逆序这这四种方式进行排序。
创建Adapter
扫描二维码关注公众号,回复: 2942411 查看本文章class StudentAdapter : RecyclerView.Adapter() {
val mCallback = StudentCallback(this) val mSortedList = SortedList<StudentBean>(StudentBean::class.java, SortedList.BatchedCallback<StudentBean>(mCallback)) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StudentViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_student, parent, false) return StudentViewHolder(view) } override fun getItemCount(): Int { return mSortedList.size() } override fun onBindViewHolder(holder: StudentViewHolder, position: Int) { val bean = mSortedList.get(position) holder.tvNoValue.text = bean.no.toString() holder.tvNameValue.text = bean.name holder.tvRankValue.text = bean.rank.toString() }
}
更新数据集
private fun resetData() { with(mAdapter.mSortedList) { beginBatchedUpdates() clear() // 当SortedList清空数据时,Adapter必须调用notifyDataSetChanged // 否则报异常 java.lang.IndexOutOfBoundsException: Inconsistency detected. mAdapter.notifyDataSetChanged() addAll(mList) endBatchedUpdates() } }