在項目中,咱們常常用到列表,在之前咱們使用RecyclerView
,伴隨着確定會有一個繼承RecyclerView.Adapter
的adapter 可是在這個adapter中,可是這個adapter中,咱們會寫較多的代碼。在com.android.support:recyclerview-v7:27.1.0
中增長了一個ListAdapter
,這個ListAdapter
讓咱們使用起來更加方便。java
在之前咱們是經過這樣的方式來進行處理android
class TestAdapter<T> : RecyclerView.Adapter<TestAdapter.ViewHolder<T>>() {
var TAG = "ADAPTER"
var mData: MutableList<T> = ArrayList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder<T> {
val inflater = LayoutInflater.from(parent.context)
return TestAdapter.ViewHolder(inflater.inflate(R.layout.item_user, parent, false))
}
override fun getItemCount(): Int {
return mData.size
}
override fun onBindViewHolder(holder: ViewHolder<T>, position: Int) {
holder.bind(mData[position])
}
fun add(t: T) {
if (t != null) {
mData.add(t)
} else {
Log.e(TAG, "the data is null")
}
notifyDataSetChanged()
}
fun addList(@NonNull ts: List<T>) {
mData.clear()
mData.addAll(0, ts)
notifyDataSetChanged()
}
fun appendList(@NonNull ts: List<T>) {
mData.addAll(mData.size, ts)
notifyDataSetChanged()
}
fun deleteItem(position: Int){
if (mData.size > position){
mData.removeAt(position)
}
notifyDataSetChanged()
}
class ViewHolder<T>(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(t: T) {
}
}
}
複製代碼
咱們大概都會作相似以上的一種事情,可是裏面有一個最大的問題,那就是不管是增長(add) 仍是刪除,都須要咱們本身處理,處理後咱們會調用notifyDataSetChanged()
方法進行刷新。 可是刷新以後咱們會發現RecyclerView
的動畫消失了。固然爲了解決這個問題,咱們能夠調用如下方法:app
這四種方法是帶動畫。 還有一種解決方式就是使用DiffUtil
ide
DiffUtil
在 support library 25.1.0 的時候就引入了,最主要的功能就是處理adapter的更新,其功能 就是比較兩個數據集,用newList和oldList進行比較,得出最小的變化量。也就是說咱們不須要再無腦的使用 notifyDataSetChanged()
。也就是說若是咱們使用了DiffUtil
,那麼咱們不須要去區別上述的四種調用方式, DiffUtil
將自動爲咱們處理而後進行調用。函數
在ListAdapter
的構造函數中,咱們須要一個DiffUtil的回調,固然咱們通常就使用DiffUtil.ItemCallback
動畫
class UserDiffCallback : DiffUtil.ItemCallback<User>() {
override fun areItemsTheSame(oldItem: User?, newItem: User?): Boolean {
return oldItem?.userId == newItem?.userId
}
override fun areContentsTheSame(oldItem: User?, newItem: User?): Boolean {
return oldItem == newItem
}
}
複製代碼
如上,咱們需重寫其中的兩個方法areItemsTheSame
和areContentsTheSame
spa
areItemsTheSame
提供了兩個對象,需你提供這個兩個對象是不是同一個對象。在User對象中有一個userId, 其表明了惟一性,因此這裏我就使用了oldItem?.userId == newItem?.userId
。這個可根據實際狀況自行判斷。code
areContentsTheSame
也提供了兩個對象,而後須要你提供這個兩個對象的內容是否一致,若是不一致,那麼 它就將對列表進行重繪和動畫加載,反之,表示你已經顯示了這個對象的內容而且沒有任何的變化, 那麼將不作任何的操做。對象
與以前的adapter沒有太多的區別,就是去掉了咱們的數據列表mData
和不在使用notifyDataSetChanged
相關 方法。繼承
class UserAdapter : ListAdapter<User, RecyclerView.ViewHolder>(UserDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return UserAdapter.ViewHolder(inflater.inflate(R.layout.item_user, parent, false))
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ViewHolder) {
holder.bind(getItem(position))
}
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
}
}
}
複製代碼
其實就是一個很簡單的Adapter,不須要任增長任何新的方法(增、刪、改),不管是增長仍是更新或者刪除, 咱們只須要使用adapter.submitList(List)
方法
可是須要注意一個問題,這個adapter.submitList(List)
方法中須要提供一個列表,這個List必須是一個新的 列表,也就是說,若是你使用的是一個已經加載了的列表,那麼將不會被加載。
ListAdapter讓開發着使用更少的代碼,而且可以讓用戶擁有視覺上的享受