RecyclerView做為ListView的替代品辟狈,已經(jīng)出了很久了菩混,既然是替代品弱贼,那自然有些ListView沒有的優(yōu)點。比如說:可以隨意切換list,grid,stagger陡鹃『嫫郑可以指定一個或多個item刷新,而不再是全部刷新萍鲸。另外可以為每個item添加動畫谎倔,在體驗上更進一步。
但是也有不少“缺點”
- divider沒以前好畫了猿推,其實是因為divider支持多種樣式,方便自己定義了捌肴。以前divider就是一根線蹬叭,現(xiàn)在可以加margin,加多條線状知,某行不加divider等需求秽五。ItemDecoration=>Item裝飾器,名副其實饥悴。
- 沒有OnItemClickListener坦喘,RecyclerView的解耦方式太漂亮了,LayoutManager負責(zé)計算布局西设,Adapter負責(zé)適配瓣铣,Holder負責(zé)渲染Item,ItemDecoration負責(zé)items間隔贷揽,ItemAnimator負責(zé)item動畫棠笑,Recycler負責(zé)回收復(fù)用。RecyclerView就是個中控啊禽绪,只負責(zé)調(diào)度蓖救。所以它為了不破壞自己的解耦,就讓每個item自己去實現(xiàn)點擊事件印屁,萬一要Drag循捺,Move,Swipe呢雄人,對吧从橘。
- 阿西巴,沒有header footer,上述2中已經(jīng)說過了洋满。RecyclerView不愛干實事兒晶乔,就負責(zé)調(diào)度,UI的事都是Adapter負責(zé)干的啊牺勾。你給RecyclerView了它也不知道給你加到哪里去正罢。想實現(xiàn),就去找Adapter吧驻民。
關(guān)于API翻具,以及RecyclerView的用法Stay就不多說了,網(wǎng)上都有回还。我們來討論討論裆泳,如何將RecyclerView真正投入到項目中去。
我們不愿意使用新東西柠硕,一是怕有bug工禾,二是怕不滿足需求,三是怕沒有現(xiàn)成的成熟的封裝類可以用蝗柔,不想自己寫闻葵。
github上有很多基于RecyclerView的封裝,Stay覺得還不夠徹底癣丧。使用起來還是不夠方便槽畔。特別是UltimateRecyclerView,根本不叫封裝胁编,簡直就是堆代碼厢钧,看起來功能強大,實際上能用到10%的樣式就不錯了嬉橙。請勿使用這種代碼早直,功能越多,改起來就更復(fù)雜啊憎夷。
Stay理想的封裝模式是這樣的:
-
大家還記得ListActivity嘛莽鸿,就是那個將ListView和Adapter定義在父類,讓子類去繼承的∈案現(xiàn)在RecyclerView支持List祥得,Grid,Stagger蒋得,不做個BaseListActivity多可惜级及,好多默認配置都可以放父類,最簡單的子類Activity只需要load數(shù)據(jù)以及bindHolder就完了额衙。
連Adapter都不用寫了饮焦。
-
以SwipeRefreshLayout為例怕吴,想要RecyclerView支持下拉刷新,加載更多县踢,必然要將兩者封裝到一起转绷,再建一個Controller類,這個Controller還是負責(zé)調(diào)度硼啤,將SwipeRefreshLayout與RecyclerView的調(diào)度方法再寫一遍议经,外層只需要跟Controller溝通。
-
想要實現(xiàn)加載更多谴返,需要讓Adapter去負責(zé)煞肾,原生的Adapter不支持,那就需要再抽一個BaseListAdapter來擴展嗓袱,itemType籍救,itemCount,onCreateFooterViewHolder都由這個抽象類來filter渠抹,這樣子類就不需要管footer這事蝙昙,只需要繼承BaseListAdapter,就自動支持加載更多梧却。
-
加載更多的footer有兩個坑耸黑,在stagger模式下,findLastVisiblePositions這返回的是數(shù)組,在list篮幢,grid模式下返回的是int,在未來可能會自定義LayoutManager为迈,那可能又會發(fā)生變化三椿,那么就需要定義一個算法,然后不同的模式都實現(xiàn)它葫辐,這樣在Controller中只需要調(diào)這個算法搜锰,拿到值就搞定了。你可以用策略模式來解決它耿战。
用策略模式蛋叼,是不想在Controller中instanceOf與強轉(zhuǎn),并且如果有自定義的LayoutManager剂陡,那以后就需要去改動Controller狈涮。
-
加載更多另一個坑就是,在grid和stagger模式下鸭栖,footer要占滿一行而不是一個span歌馍。所以grid需要SpanSizeLookup來動態(tài)改footer所占的spanCount。而stagger呢晕鹊,需要將viewholder中的itemView的LayoutParams中isFullSpan設(shè)置為true松却。確實很麻煩暴浦,但你依然可以用策略模式來解決它。
- 假如要實現(xiàn)Section分組晓锻,那就再定義一個BaseSectionListActivity去繼承BaseListActivity歌焦,再做一次封裝與隔離。這樣子類只要繼承BaseSectionListActivity就擁有了一個支持分組砚哆,下拉刷新独撇,加載更多的這樣一個控件。并且支持list窟社,grid券勺。
以上是Stay所想的封裝方式,沒有什么高深的算法灿里,只是簡單的通過控件的組合关炼,API的靈活運用。當(dāng)然如果你要支持drag匣吊,move儒拂,sticky-section-header,那就需要額外做工作了色鸳。但那些畢竟是少數(shù)社痛,將業(yè)務(wù)需求中常用的UI形式進行封裝才是必要的。
如果能看明白命雀,說明功底很扎實蒜哀,我想大家肯定也能自己實現(xiàn),或者對接那些開源RecyclerView Lib吏砂,做一個BaseListActivity, BaseListFragment還是相當(dāng)爽的撵儿,少寫了很多代碼。
如果希望參考我的封裝過程以及源代碼狐血,可以參考這篇文章:封裝那些事-100行擼一個妹紙圖