欧美+在线播放,蜜臀av在线,久久久99久久久国产自输拍,免费 黄 色 人成 视频 在 线,免费+国产+国产精品

 
您的位置:首頁(yè) >  新聞中心 > 開(kāi)發(fā)者專(zhuān)區(qū)
  開(kāi)發(fā)者專(zhuān)區(qū)
 

RecyclerView 體驗(yàn)優(yōu)化及入坑總結(jié)

來(lái)源:原創(chuàng)    時(shí)間:2018-01-29    瀏覽:0 次

前語(yǔ)

本文所講RecyclerView 是來(lái)自support 庫(kù) 26 版別,本文首要來(lái)源于本身開(kāi)發(fā)及組內(nèi)搭檔遇到問(wèn)題的經(jīng)驗(yàn)總結(jié),作為常識(shí)沉積記載一下,以備日后檢查。
本文首要解說(shuō)以下幾部分:
1.RecyclerView 滑動(dòng)體會(huì)篇

橫向ViewPager與內(nèi)嵌橫向RecyclerView之間的滑動(dòng)抵觸;
縱向RecycleView/ListView與橫向RecycleView之間的滑動(dòng)抵觸;
橫向RecyclerView ItemView滑動(dòng)不斷留在中心態(tài);
記載、康復(fù)RecyclerView翻滾偏移方位;
2.RecyclerView 入坑篇

RecyclerView導(dǎo)致的內(nèi)存走漏(support 26 + 7.0以下機(jī)型);
RecyclerView調(diào)用notifyDataSetChanged 會(huì)閃耀;
RecycleView/ListView設(shè)置itemView 為View.GONE 作用等同于View.Invisible;
RecycleView滑動(dòng)體會(huì)

1.ViewPager與橫向RecyclerView之間的滑動(dòng)抵觸

現(xiàn)在,企鵝FM項(xiàng)目中,許多頁(yè)面運(yùn)用ViewPager+ TabLayout (如主頁(yè)、詳情頁(yè)、查找成果頁(yè)等),而對(duì)應(yīng)頁(yè)面許多時(shí)分會(huì)嵌套一個(gè)橫向RecycleView,用來(lái)展示更多的信息,如下,在RecycleView中滑動(dòng)到最終一個(gè)元素時(shí),會(huì)一起帶動(dòng)ViewPager滑動(dòng),這種體會(huì)極差。
blob.png
原因剖析:

作為子View 的RecyclerView在滑到最終一個(gè)或第一個(gè)ItemView到導(dǎo)致ViewPager滑動(dòng),這必定是ViewPager在此刻對(duì)滑動(dòng)事情進(jìn)行了阻攔,處理的最簡(jiǎn)略辦法就是不讓ViewPager阻攔橫向RecyclerView的滑動(dòng)事件(即ViewPager::onInterceptTouchEvent辦法回來(lái)false),ViewPager::onInterceptTouchEvent中的Move 事件如下:
blob.png
現(xiàn)在,有以下兩種辦法使ViewPager 不去阻攔橫向RecyclerView 滑動(dòng)事情:

1).在RecyclerView 對(duì)應(yīng)滑動(dòng)事情分發(fā)中調(diào)用        

getParent().requestDisallowInterceptTouchEvent(true); 阻撓ViewPager對(duì)其MOVE或許UP事情進(jìn)行阻攔,可是考慮的要素比較多,并且作用不是太好,故拋棄這種辦法。

2).批改某些辦法,進(jìn)入到上圖if判別中

在滑動(dòng)橫向RecyclerView 到兩頭時(shí),dx != 0 && !isGutterDrag(mLastMotionX, dx) 必定滿意條件,那闡明canScroll()(用來(lái)判別一個(gè)View以及它的子View是否能夠滑動(dòng))必定回來(lái)了false, 復(fù)寫(xiě)canScroll()辦法,打log,發(fā)現(xiàn)回來(lái)公然為false,驗(yàn)證了自己的判別。

處理辦法:復(fù)寫(xiě)canScroll,當(dāng)View 是橫向RecyclerView(LinearLayoutManager 包括GridLayoutManager)時(shí),直接回來(lái)true即可處理問(wèn)題,處理代碼如下:


相似的抵觸還有ViewPager 和HorizontalScrollView 等等,處理辦法與上面相似。 

2.縱向RecyclerView/ListView 與 橫向RecyclerView 之間的滑動(dòng)抵觸

在有些時(shí)分因?yàn)楫a(chǎn)品需求,需求在縱向的RecyclerView/ListView內(nèi)嵌套一個(gè)橫向的RecyclerView,當(dāng)這個(gè)橫向RecyclerView的item 比高度較大的時(shí)分(企鵝FM書(shū)城排行榜模塊),在橫向滑動(dòng)時(shí),簡(jiǎn)略導(dǎo)致全體向上滑,體會(huì)作用較差,如下圖所示(網(wǎng)絡(luò)圖) :



形成上述現(xiàn)象的原因是:外層縱向滑動(dòng)的RecyclerView對(duì) 橫向滑動(dòng)的RecyclerView 的滑動(dòng)事情進(jìn)行了阻攔,如下圖2 所示,canScrollVertically 此刻為true,因而這兒僅僅只判別了Math.abs(dy)>mTouchSlop(能夠認(rèn)為是一個(gè)滑動(dòng)閥值,是一個(gè)定值8dp) ,并未判別方向或視點(diǎn),然后決議是否阻攔。


處理辦法 :

已然RecyclerView::onInterceptTouchEvent 內(nèi)部沒(méi)有判別滑動(dòng)視點(diǎn)或方向,那咱們就人為去判別,在上面判讀的基礎(chǔ)上持續(xù)判別 Math.abs(dy) 和Math.abs(dx) 的巨細(xì),然后決議是否阻攔:詳細(xì)剖析細(xì)節(jié)可參照此地址:

https://www.bbsmax.com/A/pRdBnnYadn/

運(yùn)用上述辦法,能夠很快處理上述滑動(dòng)體會(huì)問(wèn)題,那是不是只要上述一種處理辦法了,答案是否定的,作為一名Android 開(kāi)發(fā)者咱們知道,除了上述辦法阻攔滑動(dòng)事情外,咱們還能夠經(jīng)過(guò)getParent().requestDisallowInterceptTouchEvent(true); 讓父RecyclerView不去阻攔橫向滑動(dòng),如下是RecyclerView::onTouchEvent() ,內(nèi)部現(xiàn)已完成了requestDisallowInterceptTouchEvent(true) 。

咱們需求考慮的是,當(dāng)咱們橫向上或橫向下滑動(dòng)時(shí),需求 進(jìn)入上圖中1的判別 ,2的判別還未滿意,此刻內(nèi)部橫向RecyclerView 會(huì)阻攔內(nèi)部itemView的滑動(dòng)事情,進(jìn)而履行自己的onTouchEvent事情,然后調(diào)用requestDisallowInterceptTouchEvent(true) ,讓外層RecyclerView不去阻攔內(nèi)部RecyclerView的橫向滑動(dòng)事情,至此需求處理怎么確保先進(jìn)入1判別而不進(jìn)入2判別。


處理辦法:經(jīng)過(guò)調(diào)整TouchSlop值的巨細(xì) 

在開(kāi)端咱們已介紹RecyclerView 的默許TouchSlop 值是8dp,假如要先確保進(jìn)入1判別條件,有必要調(diào)大TouchSlop值(反射獲?。?jīng)過(guò)調(diào)整TouchSlop (按倍數(shù)調(diào)整比較簡(jiǎn)略,能夠先知道一個(gè)大致規(guī)模)驗(yàn)證,當(dāng)TouchSlop擴(kuò)展1倍時(shí)就能滿意條件。

總結(jié):上述兩種辦法各有優(yōu)缺陷,辦法1,對(duì)原生RecyclerView 侵入性較強(qiáng)(特別是對(duì)RecyclerView 進(jìn)行多層封裝的狀況下,影響比較大),長(zhǎng)處是TouchSlop 值堅(jiān)持與體系共同,不會(huì)帶來(lái)其他不知道問(wèn)題;辦法 2 ,批改辦法簡(jiǎn)略,侵略性小,缺陷,需求調(diào)整TouchSlop 值,可能還會(huì)帶來(lái)其他問(wèn)題。


3.橫向RecyclerView  ItemView 滑動(dòng)不斷留在中心態(tài)

如下圖所示,正在滑動(dòng)的模塊是書(shū)城——排行榜模塊,排行榜模塊首要由橫向RecyclerView 構(gòu)成,內(nèi)部包括兩個(gè)榜單辦法,羅列前top3的內(nèi)容,在(2)的基礎(chǔ)上處理了縱向RecyclerView 嵌套橫向RecyclerView 滑動(dòng)問(wèn)題外,還有有個(gè)小問(wèn)題那就是,RecyclerView  ItemView 滑動(dòng)多少就停在那里,這種作用不是咱們想要的,咱們想要的是滑到左面就顯現(xiàn)第一個(gè)榜單,滑到右邊就顯現(xiàn)第二個(gè)榜單。


那有沒(méi)有好的辦法做到這一點(diǎn)了,官方考慮到這一點(diǎn),針對(duì)RecyclerView 滑動(dòng)狀況,詳細(xì)介紹能夠自己去查一查,運(yùn)用適當(dāng)簡(jiǎn)略,針對(duì)上述問(wèn)題處理辦法如下:



4.記載、康復(fù)RecyclerView 翻滾偏移方位

了解RecyclerView 緩存的同學(xué)應(yīng)該知道(后邊在也會(huì)介紹RecyclerView緩存機(jī)制),當(dāng)RecyclerView中的itemView 滑出屏幕后會(huì)緩存在mCacheView 中(默許緩存最大數(shù)是2),因而當(dāng)滑出屏幕超越2后,再滑回來(lái),本來(lái)的方位信息都會(huì)被重置,關(guān)于一般的RecyclerView 沒(méi)有什么影響,可是假如內(nèi)嵌了一個(gè)橫向RecyclerView (如下圖中分類(lèi)模塊方位) ,起先”懸疑推理“ 在一排第一個(gè)方位,向左滑動(dòng)到其他方位后,再縱向滑動(dòng)外層RecyclerView ,發(fā)現(xiàn)分類(lèi)模塊第一個(gè)又變成了”懸疑推理“ ,這個(gè)是產(chǎn)品不能承受的。


那怎么批改上述問(wèn)題了,RecyclerView 布局 及方位相關(guān)信息都是由對(duì)應(yīng)LayoutManager決議,因而檢查對(duì)應(yīng)LayoutManager::onSaveInstanceState() 如下所示,內(nèi)部的確記載了position及offset 值。


處理辦法過(guò)程:

(1).在Adapter::onViewRecycled 中保存對(duì)應(yīng)LayoutManager的onSaveInstanceState ,一起記載保存下來(lái)



(2).在setData()數(shù)據(jù)給Adapter 時(shí),康復(fù)對(duì)應(yīng)LayoutManager 之前保存在數(shù)據(jù)信息
(3).保存記載RecyclerView 后的作用


RecycleView入坑

1.RecyclerView 導(dǎo)致的內(nèi)存走漏(support 26 + 7.0以下機(jī)型)

在進(jìn)行4.0 版別迭代時(shí),發(fā)現(xiàn)在之前的播送聚合頁(yè)存在RecyclerView導(dǎo)致的內(nèi)存走漏,下圖為內(nèi)存走漏的引證鏈,引證目標(biāo)能夠追到GapWorker。這兒的RecyclerView是一個(gè)橫向的RecyclerView ,作為播送聚合頁(yè)(ListView)的HeaderView。



因?yàn)椴ニ晚?yè)面是比較老的頁(yè)面,最近幾個(gè)版別也未發(fā)現(xiàn)此類(lèi)走漏,細(xì)細(xì)想一下,可能與RecyclerView 版別有關(guān)(4.0版別直接將support 庫(kù)由23.1升級(jí)到26.1版別),剛好這幾個(gè)版別,support 庫(kù) 批改了批改許多RecyclerView 的bug 及添加了許多新功能。經(jīng)過(guò)AndroidXRef 查詢知(查詢成果如下),GapWorker 公然是在support 26 新增的。


檢查GapWorker ,里邊sGapWorker 是一個(gè)ThreadLocal 帶GapWorker 的目標(biāo),一起保持了一個(gè)RecyclerView 的List目標(biāo)(經(jīng)過(guò)add  和remove 辦法進(jìn)行)。



而GapWorker的add 和remove 辦法分別在RecyclerView::onAttachedToWindow 和RecyclerView::onDetachedFromWindow 中調(diào)用,如下圖所示:



依據(jù)上面的引證鏈知,RecyclerView::onDetachedFromWindow 辦法 沒(méi)有被自動(dòng)調(diào)用,斷點(diǎn)驗(yàn)證,在退出播送頁(yè)面的時(shí)分也沒(méi)有調(diào)用(導(dǎo)致走漏),按理說(shuō)在滑動(dòng)離屏的時(shí)分就應(yīng)該調(diào)用的,莫非和RecylerView 做為L(zhǎng)istView 的HeaderView 有關(guān),順著這條思路發(fā)現(xiàn)公然和上述運(yùn)用辦法有關(guān)。

之前遇到過(guò):ListView 嵌套GridView時(shí),GridView數(shù)據(jù)紊亂問(wèn)題(7.0及其以上有問(wèn)題),里邊剛好闡明晰7.0及其以上版別,官方批改了RecylerView 做為L(zhǎng)istView 的HeaderView 狀況,滑出屏幕,不調(diào)用onDetachedFromWindow()的原因,詳細(xì)如下:





從剖析中,能夠獲取到兩個(gè)重要的信息:

GapWorker 是在support 26 以上才有的,且SDK_INT>=21,才會(huì)進(jìn)行對(duì)應(yīng)add 和remove 操作 ;

在SDK_INT< 24(7.0) 時(shí),不會(huì)自動(dòng)調(diào)用View::dispatchDetachedFromWindow()。

因而,上述問(wèn)題的處理辦是:在對(duì)應(yīng)Fragment 的onDetach() 或 其他場(chǎng)景首要去調(diào)用上圖中的ViewGroup::removeDetachedView()  (這兒需求運(yùn)用反射),詳細(xì)如下:
blob.png

2.RecyclerView調(diào)用notifyDataSetChanged 會(huì)閃耀

直接看此文章就能夠了,地址為:

https://www.jianshu.com/p/29352def27e6

3.RecycleView /ListView 設(shè)置itemView 為View.GONE 作用等同于View.Invisible

 處理辦法:

將itemView 的寬高設(shè)置成 0 ,從頭設(shè)置一下LayoutParams