使用更少代碼的ListAdapter

寫(xiě)在前面的話

在項(xiàng)目中衙荐,我們經(jīng)常用到列表,在以前我們使用RecyclerView,伴隨著肯定會(huì)有一個(gè)繼承RecyclerView.Adapter的adapter
但是在這個(gè)adapter中滩届,但是這個(gè)adapter中,我們會(huì)寫(xiě)較多的代碼被啼。在com.android.support:recyclerview-v7:27.1.0
中增加了一個(gè)ListAdapter,這個(gè)ListAdapter讓我們使用起來(lái)更加方便帜消。

存在的問(wèn)題

在以前我們是通過(guò)這樣的方式來(lái)進(jìn)行處理

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) {

        }

    }

}

我們大概都會(huì)做類似以上的一種事情棠枉,但是里面有一個(gè)最大的問(wèn)題,那就是不論是增加(add)
還是刪除券犁,都需要我們自己處理术健,處理后我們會(huì)調(diào)用notifyDataSetChanged()方法進(jìn)行刷新汹碱。
但是刷新之后我們會(huì)發(fā)現(xiàn)RecyclerView的動(dòng)畫(huà)消失了粘衬。當(dāng)然為了解決這個(gè)問(wèn)題,我們可以調(diào)用以下方法:

  • adapter.notifyItemRangeInserted(position, count);
  • adapter.notifyItemRangeRemoved(position, count);
  • adapter.notifyItemMoved(fromPosition, toPosition);
  • adapter.notifyItemRangeChanged(position, count, payload);

這四種方法是帶動(dòng)畫(huà)咳促。
還有一種解決方式就是使用DiffUtil

DiffUtil

DiffUtil在 support library 25.1.0 的時(shí)候就引入了稚新,最主要的功能就是處理adapter的更新,其功能
就是比較兩個(gè)數(shù)據(jù)集跪腹,用newList和oldList進(jìn)行比較褂删,得出最小的變化量。也就是說(shuō)我們不需要再無(wú)腦的使用
notifyDataSetChanged()冲茸。也就是說(shuō)如果我們使用了DiffUtil屯阀,那么我們不需要去區(qū)別上述的四種調(diào)用方式,
DiffUtil將自動(dòng)為我們處理然后進(jìn)行調(diào)用轴术。

DiffUtil.ItemCallback

ListAdapter的構(gòu)造函數(shù)中难衰,我們需要一個(gè)DiffUtil的回調(diào),當(dāng)然我們一般就使用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
    }
}

如上逗栽,我們需重寫(xiě)其中的兩個(gè)方法areItemsTheSameareContentsTheSame

areItemsTheSame

areItemsTheSame提供了兩個(gè)對(duì)象盖袭,需你提供這個(gè)兩個(gè)對(duì)象是否是同一個(gè)對(duì)象。在User對(duì)象中有一個(gè)userId,
其代表了唯一性彼宠,所以這里我就使用了oldItem?.userId == newItem?.userId鳄虱。這個(gè)可根據(jù)實(shí)際情況自行判斷。

areContentsTheSame

areContentsTheSame也提供了兩個(gè)對(duì)象凭峡,然后需要你提供這個(gè)兩個(gè)對(duì)象的內(nèi)容是否一致拙已,如果不一致,那么
它就將對(duì)列表進(jìn)行重繪和動(dòng)畫(huà)加載摧冀,反之倍踪,表示你已經(jīng)顯示了這個(gè)對(duì)象的內(nèi)容并且沒(méi)有任何的變化,
那么將不做任何的操作按价。

ListAdapter

與之前的adapter沒(méi)有太多的區(qū)別惭适,就是去掉了我們的數(shù)據(jù)列表mData和不在使用notifyDataSetChanged相關(guān)
方法。


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) {
            
        }
    }

}

其實(shí)就是一個(gè)很簡(jiǎn)單的Adapter楼镐,不需要任增加任何新的方法(增癞志、刪、改)框产,無(wú)論是增加還是更新或者刪除凄杯,
我們只需要使用adapter.submitList(List)方法

但是需要注意一個(gè)問(wèn)題错洁,這個(gè)adapter.submitList(List)方法中需要提供一個(gè)列表,這個(gè)List必須是一個(gè)新的
列表戒突,也就是說(shuō)屯碴,如果你使用的是一個(gè)已經(jīng)加載了的列表,那么將不會(huì)被加載膊存。

總結(jié)

ListAdapter讓開(kāi)發(fā)著使用更少的代碼,并且能夠讓用戶擁有視覺(jué)上的享受

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末导而,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子隔崎,更是在濱河造成了極大的恐慌今艺,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爵卒,死亡現(xiàn)場(chǎng)離奇詭異虚缎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钓株,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門实牡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轴合,你說(shuō)我怎么就攤上這事创坞。” “怎么了值桩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵摆霉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我奔坟,道長(zhǎng)携栋,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任咳秉,我火速辦了婚禮婉支,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘澜建。我一直安慰自己向挖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布炕舵。 她就那樣靜靜地躺著何之,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咽筋。 梳的紋絲不亂的頭發(fā)上署恍,一...
    開(kāi)封第一講書(shū)人閱讀 49,929評(píng)論 1 290
  • 那天剧包,我揣著相機(jī)與錄音,去河邊找鬼。 笑死新思,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛔翅,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了爵政?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掺出,失蹤者是張志新(化名)和其女友劉穎汤锨,沒(méi)想到半個(gè)月后百框,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年钧嘶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了有决。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片书幕。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡台汇,死狀恐怖苟呐,靈堂內(nèi)的尸體忽然破棺而出俐筋,到底是詐尸還是另有隱情,我是刑警寧澤笆呆,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布赠幕,位于F島的核電站劣坊,受9級(jí)特大地震影響屈留,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜康二,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望产雹。 院中可真熱鬧,春花似錦夕土、人聲如沸瘟判。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)陕壹。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間又碌,已是汗流浹背绊袋。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工皂岔, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留展姐,地道東北人圾笨。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓土铺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親究恤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子后德,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容