亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

詳解iOS 滾動視圖的復用問題解決方案

2020-07-26 02:59:59
字體:
來源:轉載
供稿:網友

LazyScroll是什么

LazyScrollView 繼承自ScrollView,目標是解決異構(與TableView的同構對比)滾動視圖的復用回收問題。它可以支持跨View層的復用,用易用方式來生成一個高性能的滾動視圖。

為什么要用LazyScrollView

我們在做首頁的時候,往往展示的東西會很多,隨著View數量逐漸膨脹,沒有一套復用回收機制的ScrollView已經影響到性能了,迫切需要處理對ScrollView中View的復用和回收。使用TableView只能用來解決同類Cell的展示,然而在實際的場景中在ScrollView里面,View的種類往往會比較多,所以使用TableView不適合我們的場景。
而UICollectionView本身的布局和復用回收機制不夠靈活,用起來也較為繁瑣。所以誕生了LazyScrollView去解決這個問題。這也是天貓iOS客戶端的首頁落地方案。

LazyScroll使用

LazyScrollView的使用和TableView很像,不過多了一個需要實現的方法:返回對應index的View 相對LazyScrollView的絕對坐標。

實現LazyScrollViewDatasource

類似TableView的用法,我們需要使用方實現LazyScrollViewDatasource的Delegate。

@protocol TMMuiLazyScrollViewDataSource <NSObject>@required//ScrollView展示item個數- (NSUInteger)numberOfItemInScrollView:(TMMuiLazyScrollView *)scrollView;//要求根據index直接返回RectModel- (TMMuiRectModel *)scrollView:(TMMuiLazyScrollView *)scrollView rectModelAtIndex:(NSUInteger)index;//返回下標所對應的view- (UIView *)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID;

LazyScrollView的核心是在初始狀態就得知所有View應該顯示的位置。第一個方法很簡單,獲取LazyScrollView中item的個數。第二個方法需要按照Index返回TMMuiRectModel ,它會攜帶對應index的View 相對LazyScrollView的絕對坐標。

這里出現了一個TMMuiRectModel ,這是個什么東西呢?我們看一下代碼:

@interface TMMuiRectModel:NSObject//轉換后的絕對值rect@property (nonatomic,assign) CGRect absRect;//業務下標@property (nonatomic,copy) NSString *muiID;

這里有兩個屬性,absRect是LazyScroll中的View相對LazyScrollView的絕對坐標,muiID是這個View在LazyScrollView中唯一的標識符,可賦值也可不賦值。

第三個方法,返回View。

@interface UIView(TMMui)

//索引過的標識,在LazyScrollView范圍內唯一@property (nonatomic, copy) NSString *muiID;//重用的ID@property (nonatomic, copy) NSString *reuseIdentifier;

首先,我們在UIView之外加了一個Category,這個category可以讓View攜帶muiID和reuseIdentifier,對于返回的View來說,只需要在乎對View的reuseIdentifier賦值,muiID的賦值會在lazyScrollView中處理掉。reuseIdentifier相同的View會被復用,如果這個View的reuseIdentifier是nil或者空字符串,則不會被復用。

LazyScrollView內部原理分析

首先來看一個簡單的案例:

根據DataSource獲取所有的TMMuiRectModel

根據DataSource的Delegate,拿到所有的View應該被顯示的位置。這一步,核心是拿到的位置是確定的。根據Demo,我們觀察從 0/1 - 2/3 之間這些View,這個時候LazyScrollView拿到的Rect如下:

Index 標號(MUIID) Rect
0 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150
1 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150)
2 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150)
3 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150
4 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150)
5 1/1 origin = (x = 192.5, y = 426), size = (width = 84, height = 84)
6 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56)
7 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84)
8 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150)
9 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150)
10 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150)

排序

拿到了這些位置之后,接下來做的事情就是排序。排序生成的索引會有兩個:根據頂邊(y)升序排序的索引和根據底邊(y+height)降序排序的索引。

根據頂邊(y)升序排序的索引

Index 標號(MUIID) Rect
0 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150
1 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150)
2 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150)
3 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150
4 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150)
5 1/1 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56)
6 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56)
7 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84)
8 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150)
9 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150)
10 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150)

根據底邊(y+height)降序排序的索引

Index 標號(MUIID) Rect
0 2/2 origin = (x = 25, y = 860), size = (width = 325, height = 150)
1 2/1 origin = (x = 25, y = 695), size = (width = 325, height = 150)
2 2/0 origin = (x = 25, y = 530), size = (width = 325, height = 150)
3 1/0 origin = (x = 5, y = 360), size = (width = 177.5, height = 150)
4 1/2 origin = (x = 192.5, y = 360), size = (width = 177.5, height = 56)
5 1/3 origin = (x = 286.5, y = 426), size = (width = 83.5, height = 84)
6 1/1 origin = (x = 192.5, y = 426), size = (width = 84, height = 84)
7 0/2 origin = (x = 25, y = 180), size = (width = 156, height = 150)
8 0/3 origin = (x = 194, y = 180), size = (width = 156, height = 150
9 0/0 origin = (x = 25, y = 15), size = (width = 156, height = 150
10 0/1 origin = (x = 194, y = 15), size = (width = 156, height = 150)

查找

前兩步是在執行完reload,在視圖還沒有生成的時候就開始做了,而接下來的步驟在要生成視圖(初始化或滾動的時候)才會去做。

我們設定了Buffer為上下各20,滾動超過20個像素后才會指定查找視圖并顯示的動作。舉個例子,如下圖,紅圈是應該顯示的區域。

如上圖所示,現在已知的是紅圈頂邊y是242,底邊y是949,加上緩沖區Buffer,應該是找222 - 969 之間的View。我們要做的是,找到底邊y小于969的Model和頂邊y大于222的Model,取交集,就是我們要顯示的View。

采用的方法為二分查找,在根據頂邊升序排序的索引中找949,找到的index為0(MUIID為2/2),我們使用一個Set,把根據頂邊排序中index >= 0 的元素先放在這里。獲取的Set中包含的muiID為 0/0,0/1,0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2。

根據底邊排序的索引中找222,找到的index為2,我們把index >= 2的元素放在另一個Set,獲取的Set中包含的muiID為0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2

兩個Set取交集,得到的就是我們的ResultSet,這里面都是我們要顯示View的Model,它們的muiID是0/2,0/3,1/0,1/1,1/2,1/3,2/0,2/1,2/2。

回收、復用、生成

我們知道了應該顯示哪些View,但是我們之后做的第一步是把不需要顯示的View加入到復用池中。LazyScroll可以取到當前顯示了的View,拿當前顯示的View的muiID和將要顯示view的Model的muiID做對比,可以知道當前顯示的View哪些應該被回收。

LazyScrollView中有一個Dictionary,key是reuseIdentifier,Value是對應reuseIdentifier被回收的View,當LazyScrollView得知這個View不該再出現了,會把View放在這里,并且把這個View hidden掉。

然后,用LazyScrollView會去調用datasource。

- (UIView *)scrollView:(TMMuiLazyScrollView *)scrollView itemByMuiID:(NSString *)muiID;

復用還是不復用,是由datasource決定的。如果要復用,需要datasource方法內調用,即:

- (UIView *)dequeueReusableItemWithIdentifier:(NSString *)identifier

獲取復用的View,這個方法取出來的View就是在上一段所說的Dictionary中拿的。
最后我們看一下LazyScrollView的使用流程:找到所有View將要顯示的位置 亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

欧美亚洲国产日本| 91久久国产婷婷一区二区| 亚洲男人的天堂在线| 亚洲第一网中文字幕| 欧美黑人视频一区| 97av在线影院| 久热精品视频在线观看一区| 欧美日韩国产在线播放| 国产精品午夜国产小视频| 国产精品福利在线观看| 欧美一区二区色| 国产精品伦子伦免费视频| 日韩欧美亚洲国产一区| 国产精品国模在线| 欧美理论电影网| 亚洲成色777777女色窝| 国产精品久久久精品| 欧美日韩中文字幕在线视频| 少妇高潮 亚洲精品| 国产精品久久久久高潮| 日本韩国欧美精品大片卡二| 国产精品入口免费视频一| 国产婷婷成人久久av免费高清| 亚洲精品99999| 欧美午夜片欧美片在线观看| 伊人成人开心激情综合网| 亚洲美女性视频| 国产suv精品一区二区三区88区| 精品国产乱码久久久久久婷婷| 不卡中文字幕av| 国产精品一二三视频| 国产亚洲精品日韩| 亚洲精品美女久久久久| 亚洲精品不卡在线| 国产精品久久久久久久9999| 成人激情在线观看| 久久久99免费视频| 国产日韩精品在线| 色综合久久天天综线观看| 欧美在线视频一区| 国产精品精品久久久| 韩国欧美亚洲国产| 日韩欧美中文第一页| 国产91九色视频| 欧美大片网站在线观看| 亚洲久久久久久久久久久| 日韩电影第一页| 91久久综合亚洲鲁鲁五月天| 国产精品久久久久久亚洲调教| 精品久久久久久久久中文字幕| 92福利视频午夜1000合集在线观看| 97精品欧美一区二区三区| 欧美多人爱爱视频网站| 上原亚衣av一区二区三区| 亚洲视频在线看| 国自产精品手机在线观看视频| 亚洲欧美日本精品| 欧美视频国产精品| 精品国产乱码久久久久久天美| 日本高清视频一区| 日韩欧美视频一区二区三区| 亚洲一区二区三区香蕉| 九九热99久久久国产盗摄| 欧美有码在线观看视频| 欧美大胆在线视频| 奇门遁甲1982国语版免费观看高清| 国产精品久久久久999| 欧美疯狂做受xxxx高潮| 视频在线观看99| 精品欧美一区二区三区| 精品无码久久久久久国产| 精品久久久久久久久久| 久久成人一区二区| 丝袜亚洲另类欧美重口| 亚洲欧美激情视频| 久久九九免费视频| 国产成人jvid在线播放| 国产亚洲日本欧美韩国| 5566日本婷婷色中文字幕97| 色综久久综合桃花网| 91久久国产综合久久91精品网站| 精品久久久香蕉免费精品视频| 成人av资源在线播放| 国产日韩亚洲欧美| 久久精品国产综合| 不卡av日日日| 日韩黄色在线免费观看| 成人亚洲综合色就1024| 日韩中文有码在线视频| 成人精品一区二区三区| 少妇高潮久久久久久潘金莲| 国产主播精品在线| 国产成人+综合亚洲+天堂| 国产精品私拍pans大尺度在线| 成人黄色影片在线| 欧美福利视频在线| 欧洲成人免费视频| 久久夜精品香蕉| 亚洲第一区中文字幕| 亚洲欧美日韩中文在线制服| 国产成一区二区| 日本久久久久久久久久久| 日本精品久久中文字幕佐佐木| 国产精品欧美日韩久久| 一区二区三欧美| 国产午夜精品美女视频明星a级| 精品久久久久久久大神国产| 在线播放国产一区中文字幕剧情欧美| 黄网站色欧美视频| 奇门遁甲1982国语版免费观看高清| 亚洲精品一区中文| 久久久亚洲网站| 成人午夜黄色影院| 97精品国产97久久久久久春色| 精品视频久久久| 亚洲成色777777女色窝| 美日韩在线视频| 久久亚洲精品国产亚洲老地址| 日韩精品999| 色偷偷偷亚洲综合网另类| 欧美色另类天堂2015| 国产视频自拍一区| 亚洲女人被黑人巨大进入| 亚洲成人网久久久| 亚洲精品一区在线观看香蕉| 中文字幕精品影院| 成人国产精品一区二区| 亚洲欧美国产另类| 在线观看免费高清视频97| 色综合久久精品亚洲国产| 国产精品偷伦一区二区| 精品国产31久久久久久| 奇米四色中文综合久久| 亚洲性av网站| 中文字幕精品国产| 国产精品久久国产精品99gif| 2018国产精品视频| 97国产一区二区精品久久呦| 国产成人在线一区| 久久久久北条麻妃免费看| 精品久久久久久久久久久久久久| 久久久久久网站| 亚洲美女av在线| 亚洲黄页网在线观看| 91精品国产91久久久久久不卡| 91中文字幕在线| 久久精品国产精品亚洲| 久久这里有精品视频| 亚洲丁香婷深爱综合| 91精品国产成人www| 国产欧美日韩精品在线观看| 亚洲精品福利免费在线观看| 国产精品青草久久久久福利99| 中文字幕在线看视频国产欧美在线看完整| 久久欧美在线电影| 久久久久久久成人| 亚洲免费中文字幕| 欧美片一区二区三区| 久久伊人精品天天| 国产精品18久久久久久首页狼| 亚洲综合小说区| 亚洲3p在线观看| 日韩亚洲精品视频| 懂色av一区二区三区|