整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          UICollectionView的數據預加載及圖片加載邏輯的優化

          原文

          主題 iOS開發 C語言

          當App中使用了 以瀑布流的形式來呈現數據時,站在用戶的角度,用戶在自上至下一頁一頁瀏覽這些內容的過程中,當用戶感到滑動很流暢自然,每頁內容從無到有需要用戶等待的時間很短甚至幾乎感覺不到,那么 才會帶給用戶一個很好的體驗。本文介紹了為了達到這兩個目的所作出的一些客戶端的優化。

          數據的預加載

          數據預加載的目的是不必等到用戶某一時刻瀏覽到的末尾了,也即本地已經沒有更多數據展示了才去發請求拿下一頁數據,而是有一個預判,用戶就快要看完本地的數據了,可以向Server要下一頁數據了!

          為了實現預加載,最開始的方案是在UI層面的預判。根據 的基類是 ,大致思路是對于沿豎直方向滾動的,考察它的 .y 和 .height ,結合的 frame.size.height ,可以計算全部內容底下還有多高沒展示出來,如果高度小于我們預先設定的閾值(用戶快滑到底了),那么就觸發加載下一頁的請求。

          這樣做似乎沒什么問題,但是仔細想想,其實并不優雅。一方面,一旦有UI調整的需求,每行的高度有調整時,我們也要去調整閾值,來決定是否去請求下一頁數據;另一方面,App中不同場景下的每行高度不同,需要根據不同場景去Tuning,找出合適的閾值。

          后來很自然想到在邏輯上進行預判,也就是我們現在使用的方案。

          每個Cell都需要一個數據模型對象(Data Object,下稱DTO)來支持它的顯示,通常客戶端拿到的服務端返回的數據后,做一系列的解析,得到一個一個DTO,用以支持的展示。到代碼層面DTO們被保存在一個數組里,任意時刻在正確的狀態下 的總Cell數量應該跟當前本地DTO的個數相等,Cell跟DTO是一一對應的關系, 數據的預加載本質上就是DTO的預加載 。

          用戶在滾動 時,當 根據預定的配置覺得它該展示某行某列的Cell時,會向它的[2]發送 :th: 消息[3],詢問那行那列該展示什么,這個方法返回一個Cell對象, 拿到這個Cell后就把它展示在相應位置。通常這個方法中要做的重要事情就是去上文提到的保存DTO的數組中根據Cell的行列索引找到這個Cell對應的DTO,根據DTO對Cell配置一番,返回給 。

          順著這個思路,在這個方法中可以知道當前 需要展示的Cell的索引,由于Cell跟DTO是一一對應的關系,那我們也知道了當前需要的DTO在總數據模型對象中的索引,當剩下的數據模型對象不夠支持一頁的顯示時,就去請求下一頁。

          表達的可能有點抽象,假設請求一次Server返回20個DTO,過程可以更形象化一點:

          - : 數據源數據源,用戶滑到第181個Cell要露出來了,快給我!

          - : 好的,我首先要去拿第181個Cell對應的DTO,根據這個配置好一個Cell給你去展示!

          等等,你都已經展示到第181個Cell了啊!我發現DTO目前本地總共只有200個,200 - 181 = 19 < 20不夠支持你展示下一頁所需要的20個Cell了,我先發起一個異步請求,去拿新一頁的DTO!

          關鍵代碼,很簡單:

          = .count; // 目前本地有的DTO數量

          = .row; // 當前需要的Cell索引,也即當前需要的數據模型索引

          if ( - < 19) {

          [self ];

          要注意的問題是要做好防止重復發送請求的保護工作。

          圖片加載邏輯優化

          當 的每個Cell都需要展示一個(或多個)圖片時,在上文提到的根據DTO配置Cell過程中,會根據DTO中指定的圖片的URL,發送一個異步的圖片請求,等到圖片請求完畢了,再把圖片展示到對應的Cell上(當然,可以把這一切交給 : )。

          或許你會問,加載圖片已經是異步了啊,我還要優化什么?不,這遠遠不夠。在實際的測試中,這種樸素的做法依然會帶來明顯的滑動過程的卡頓。使用進行profile發現,在滑動過程中始終會丟那么15幀左右,不能忍!

          再回到 繼承自 上來。通過 的,我們能感知到滑動過程中的各種關鍵狀態,包括用戶的手是否正在拖拽,以及是否正在滑動、減速等等,這就是我們優化的秘密武器!

          那么,本著不該做的事情不要做,或者等到不得不做的時候再做的原則,讓我們分析用戶在滑動的過程中有哪些地方可以細摳。

          加載邏輯正確圖片程序_頁面加載邏輯_圖片預加載程序的正確邏輯

          用戶在滑動(拖拽)時(手與屏幕正在接觸),很有可能是用戶在認真逐個瀏覽每個Cell,要去加載當前可見Cell的圖片

          用戶滑動結束后,手離開了屏幕,并引發了減速時, 預判 減速結束后靜止時的狀態,對于那些將來靜止時用戶可見的Cell,提前去加載它們的圖片;對于那些只是“曇花一現”的Cell,即它們只是在減速的過程中出現那么一剎那,就被“頂”上去了,只加載這些Cell中圖片在本地有緩存的圖片(從內存中加載,不值得去發網絡請求,即使是異步的也不值得)

          減速結束后,處于靜止狀態,加載當前全部可見Cell的圖片

          OK,那么來看我們怎么實現它。

          對于的每個Cell,我們給它添加一個異步加載圖片的方法 。直接上關鍵代碼,看了便知。

          // 將來靜止時可見的區域,同時也是標識當前是正在被用戶拖拽還是已經被拖拽完畢并正在減速

          @ (, strong) CGRect *;

          #pragma mark -

          - ( *):( *) th:( *) {

          // ....

          [self :cell :];

          // ....

          #pragma mark -

          - (void)ragging:( *) {

          self. = nil;

          [self ells];

          - (void)gging:( *) :(CGPoint) :(inout CGPoint *) {

          self. = (->x, ->y, .frame.size.width, .frame.size.height);

          - (void):( *) {

          self. = nil;

          [self ells];

          #pragma mark - Decide to Load Image For Cells

          - (void):( *)cell

          :( *) {

          // Cell的是指派給Cell的新的圖片URL,在根據Cell的DTO配置Cell時為其賦值

          if (!cell.) {

          return;

          // Cell的是Cell的當前正在顯示的圖片URL

          if (![cell. :cell.] || cell.derNow) {

          *manager = [ ];

          *attr = [self. :];

          CGRect = attr.frame;

          BOOL = YES;

          // 如果正在減速而且當前Cell的frame不在將來滑動停止后的可見區域

          if (self. && !(self.., )) {

          // 那么只有Cell的在內存的緩存中,才去加載它

          * = [ ];

          *key = [manager :[NSURL :cell.]];

          if (![ ForKey:key]) {

          = NO;

          if () {

          [cell ];

          - (void)ells {

          NSArray * = [self. ];

          for ( *cell in ) {

          * = [self. :cell];

          [self :cell :];

          做了這些努力后,再去profile一下,發現網速良好情況下滑動時幀率只丟了那么1、2幀,而且滑動起來無明顯卡頓!

          要么不做,要么做絕

          哈哈,這個有點狠啊,頗有朱元璋的風格。

          做了這么多后,我們發現,數據預加載完畢后,向發送 消息通知它數據模型變化時,就在這一瞬間,還是會導致卡頓那么一下下。

          好吧不能忍,封裝一個我們自己的 方法,在這里簡單的hold住reload,根據上文中的 屬性的標記作用,當且僅當在減速停止后,再去真正向它發送 消息。在這里僅提供思路,不做贅述了。

          此外,在開發中,我們把這一系列的方法以 類的形式做一個封裝,這樣不管誰是的或者都可以從容應對。

          數據結構——關鍵路徑

          ——本節內容為王道考研《數據結構》P67視頻內容筆記。

          目錄

          一、基本概念 1.AOE網

          在帶權有向圖中,以頂點表示事件,以有向邊表示活動,以邊上的權值表示完成該活動的開銷(如完成活動需要的時間),稱之為用邊表示活動的網絡,簡稱AOE網。

          (1)在AOE網中僅有一個入度為0的頂點,稱為開始頂點(源點),它表示整個工程的開始;

          (2)也僅有一個出度為0的頂點,稱為結束頂點(匯點),它表示整個工程的結束。

          關鍵路徑上可以有虛假活動_虛假交易90天報名活動_建寧縣有房產證可以上小學嗎

          2.AOE網的性質

          (1)只有在某頂點所代表的事件發生后,從該頂點出發的各有向邊所代表的活動才能開始;

          (2)只有在進入某頂點的各有向邊所代表的活動都已結束時,該頂點所代表的事件才能發生,另外有些活動是可以并行進行的。

          3.關鍵路徑

          從源點到匯點的有向路徑可能有多條,所有路徑中,具有最大路徑長度的路徑稱為關鍵路徑,而把關鍵路徑上的活動稱為關鍵活動。

          完成整個工程的最短時間就是關鍵路徑的長度,若關鍵活動不能按時完成,則整個工程的完成時間就會延長。

          虛假交易90天報名活動_建寧縣有房產證可以上小學嗎_關鍵路徑上可以有虛假活動

          4.最早最晚時間

          (1)事件vk的最早發生時間ve(k):決定了所有從vk開始的活動能夠開工的最早時間;

          (2)活動ai的最早開始時間e(i):指該活動弧的起點所表示的事件的最早發生時間;

          (3)事件vk的最遲發生時間vl(k):指在不推遲整個工程完成的前提下,該事件最遲必須發生的時間;

          (4)活動ai的最遲開始時間l(i):指該活動弧的終點所表示事件的最遲發生時間與該活動所需時間之差;

          (5)活動ai的時間余量:d(i)=l(i)-e(i),表示在不增加完成整個工程所需總時間的情況下,活動ai可以拖延的時間;

          (6)若一個活動的時間余量為0,則說明該活動必須要如期完成,d(i)=0即l(i)=e(i)的活動ai是關鍵活動,由關鍵活動組成的路徑就是關鍵路徑。

          二、求關鍵路徑 1.步驟

          (1)求所有事件的最早發生時間ve();

          (2)求所有事件的最遲發生時間vl();

          (3)求所有活動的最早發生事件e();

          (4)求所有活動的最遲發生時間l();

          虛假交易90天報名活動_關鍵路徑上可以有虛假活動_建寧縣有房產證可以上小學嗎

          (5)求所有活動的時間余量d();

          (6)d(i)=0的就是關鍵活動,所有關鍵活動組成的路徑即為關鍵路徑。

          2.舉例

          虛假交易90天報名活動_關鍵路徑上可以有虛假活動_建寧縣有房產證可以上小學嗎

          建寧縣有房產證可以上小學嗎_虛假交易90天報名活動_關鍵路徑上可以有虛假活動

          虛假交易90天報名活動_關鍵路徑上可以有虛假活動_建寧縣有房產證可以上小學嗎

          虛假交易90天報名活動_建寧縣有房產證可以上小學嗎_關鍵路徑上可以有虛假活動

          關鍵路徑上可以有虛假活動_虛假交易90天報名活動_建寧縣有房產證可以上小學嗎

          三、關鍵活動/路徑特性

          1.若關鍵活動耗時增加,則整個工程的工期將增長;

          2.縮短關鍵活動的時間,可以縮短整個工程的工期;

          3.當縮短到一定程度時,關鍵活動可能會變成非關鍵活動;

          4.可能有多條關鍵路徑,只提高一條關鍵路徑上的關鍵活動速度并不能縮短整個工程的工期,只有加快那些包括在所有關鍵路徑上的關鍵活動才能達到縮短工期的目的。


          主站蜘蛛池模板: 三级韩国一区久久二区综合| 无码人妻精品一区二区三区东京热| 亚洲色婷婷一区二区三区| 亚洲国产成人一区二区精品区| 无码中文字幕乱码一区| 国产精品538一区二区在线| 国产一区二区不卡在线播放| 日韩精品无码中文字幕一区二区 | 日本丰满少妇一区二区三区| 日韩精品无码一区二区三区不卡 | 一区二区三区免费高清视频| 日韩视频一区二区在线观看 | 无码一区二区三区在线| 中文字幕一区二区三区久久网站| 国产精品一区二区久久| 日韩一区二区视频在线观看| 蜜桃无码AV一区二区| 精品人妻无码一区二区三区蜜桃一 | 国产一区二区三区在线观看影院| 亚洲中文字幕在线无码一区二区| 亚洲精品国产suv一区88| 国产丝袜无码一区二区三区视频| 亚洲av成人一区二区三区观看在线| 91秒拍国产福利一区| 一区在线观看视频| 日韩一区二区三区在线观看| 熟女少妇精品一区二区| 乱精品一区字幕二区| 国产在线步兵一区二区三区| 色婷婷亚洲一区二区三区| 亚洲国产综合无码一区二区二三区| 中文字幕一区二区人妻性色| 久久亚洲中文字幕精品一区四 | 无码人妻精品一区二区三区99仓本 | 一区二区精品在线观看| 日本精品一区二区三区视频| 免费无码毛片一区二区APP| 日韩免费一区二区三区| 国产福利精品一区二区| 香蕉一区二区三区观| 韩国福利视频一区二区|