1. 程式人生 > >利用runLoop加載高清大圖

利用runLoop加載高清大圖

sde log 完成 red get 網絡 server lease 技術分享

一、什麽是runLoop

  1、說白了,runloop就是運行循環

  2、runloop,他是多線程的法寶

    通常來講,一個線程一次只能執行一個任務,執行完之後就退出線程。但是,對於主線程是不能退出的,因此我們需要讓主線程即使任務執行完畢,也可以繼續等待接收事件而不退出,那麽runloop就可以做到。

    但是非主線程通常來說就是為了執行某一任務的,執行完畢就需要歸還資源,因此默認是不運行runloop的。

  3、每一個線程對應都有一個runloop,只是默認只有主線程的runloop是開啟的,其他子線程的runloop是默認不啟動的,若要啟動需要程序員手動啟動。

  

二、runloop作用

  1、保證程序不退出

  2、負責監聽所有的事件(sources、observe、timer)(觸摸、時鐘、網絡事件)

  3、runloop非常懶,有任務就處理,沒有就睡眠

  4、runloop負責在一次循環中渲染UI

三、runloop模式

  NSRunLoopDefaultMode:App的默認Mode,通常主線程是在這個Mode下運行
  UITrackingRunLoopMode:處理UI事件的mode
  NSRunLoopCommonModes:這是一個占位用的Mode,不是一種真正的Mode(默認在NSRunLoopDefaultMode和UITrackingRunLoopMode這兩種模式下

  UIInitializationRunLoopMode:在剛啟動App時進入的第一個Mode,啟動完成後不再使用
  GSEventReceiveRunLoopMode:接受系統事件的內部Mode,通常用不到

一個場景:加載多張高清大圖時拖拽tableView,導致界面卡頓

  分析一:

    加載多張高清大圖:需要加入runloop,在運行循環時渲染UI,進入UITrackingRunLoopMode模式

    拖拽tableView:需要加入runloop,在運行循環時處理觸摸事件,進入UITrackingRunLoopMode模式

    加載多張高清大圖,相當於runloop一次循環渲染了多張大圖(多個任務),占用了這次循環的大部分時間,導致界面卡頓    

  解決方案:讓runloop一次循環只渲染一張大圖(只幹一件事),定義觀察者,每次循環添加一張圖片進行渲染!

  代碼以及實現已經有大神整理好了:https://blog.csdn.net/liyanjun201/article/details/79096289

以下是其他大神整理的關於runloop的資料 很全面 https://blog.csdn.net/qq_30513483/article/details/53373905

RunLoop是什麽,有什麽作用,如何獲取?

  • 定義
    • RunLoop的實質是一個死循環,用於保證程序的持續運行,只有當程序退出的時候才會結束(由main函數開啟主線程的RunLoop)
  • 作用
    • 保持程序的持續運行
    • 處理App中的各種事件(觸摸、定時器、Selector事件)
    • 節省CPU資源,提高程序性能(該做事做事,沒事做休息)
  • 獲取方法
    • 使用NSRunLoop(面向對象)或者CFRunLoopRef(底層C語言)

RunLoop的原理

  • RunLoop開啟一個循環事件,並接受輸入事件,接受的事件來自兩種不同的來源:
    • 輸入源(input source)(傳遞異步事件)
    • 定時源(timer source)(傳遞同步事件)
  • RunLoop接收到消息後采用handlePort、customSrc、mySelector和timerFired等四個方法處理對應的事件
  • 當RunLoop沒有接收到消息時,則進入休眠狀態,以保持程序持續運行
技術分享圖片
RunLoop的原理

RunLoop接收幾種輸入源,系統默認定義了幾種模式?

  • 輸入源有兩種
    • 基於端口的輸入源(port)
    • 自定義的輸入源(custom)
  • 系統定義的RunLoop模式有五種,最常用的有三種,如下所示:
    • NSDefaultRunLoopMode
      • 默認模式,主線程中默認是NSDefaultRunLoopMode
    • UITrackingRunLoopMode
      • 視圖滾動模式,RunLoop會處於該模式下
    • NSRunLoopCommonModes
      • 並不是真正意義上的Mode,是一個占位用的“Mode”,默認包含了NSDefaultRunLoopMode和UITrackingRunLoopMode兩種模式

RunLoop模式的原理和使用註意點?

  • 原理和註意點
    • 一個RunLoop包含若幹個Mode,每個Mode又包含若幹個Source、Observer、Timer(如下圖所示)
    • 每次RunLoop啟動,只能指定一個Mode,這個Mode被稱為CurrentMode
    • 如果需要切換Mode,只能退出Loop,再重新指定一個Mode進入, 以使不同組之間的Source、Observer、Timer互不受影響
技術分享圖片
RunLoopMode

RunLoop和線程有什麽關系

  • RunLoop與線程是一一對應的
  • 程序啟動時,主線程默認會自己創建RunLoop,並設置為Default模式
  • 創建子線程時,必須獲取當前線程的RunLoop並啟動它

NSTimer和RunLoop的關系?

  • NSTimer需要添加到Runloop中, 才能執行的情況
  • NSTimer默認被添加到Runloop中, 直接執行的情況

NSTimer準確嗎,如果不準確,如何設計一個準確的timer?

  • 不準確
  • 準確的Timer應該和當前線程的RunLoopMode保持一致

TableView/ScrollView/CollectionView滾動時為什麽NSTimer會停止?

  • 一個RunLoop不能同時共存兩個mode
  • 當滾動視圖滾動時,當前RunLoop處於UITrackingRunLoopMode,
  • NSTimer的RunLoopMode和當前線程的RunLoopMode不一致,所以會停止
  • 解決方法:將timer的runloopMode改為UITrackingRunLoopMode或者NSRunLoopCommonModes

如果NSTimer在分線程中創建,會發生什麽,應該註意什麽?

  • NSTimer沒有啟動
    • 在主線程中,系統默認創建並啟動主線程的runloop
    • 在分線程中,系統不會自動啟動runloop,需要手動啟動
  • 解決方法:
    • 啟動分線程的runLoop

在異步線程中下載很多圖片,如果失敗了,該如何處理?請結合RunLoop來談談解決方案

  • 在異步線程中啟動一個RunLoop重新發送網絡請求,下載圖片

如果程序啟動就需要執行一個耗時操作,你會怎麽做?

  • 開啟一個異步的子線程,並啟動它的RunLoop來執行該耗時操作

runloop與autoreleasepool的關系

如果在分線程中啟動一個異步請求,會有什麽問題?

判斷其是否請求結束,如果未結束,要保持當前線程一直啟動,直到結束

程序啟動時,runloop是如何工作的?如果程序啟動就需要執行一個耗時操作,你會怎麽做?

程序啟動時,系統默認創建並啟動主線程的runloop,runloop會默認創建兩個Observe來進行監聽runloop的進出和睡眠,有事情的時候就去做,沒事的休眠

(線程(創建)-->runloop將進入-->最高優先級OB創建釋放池-->runloop將睡-->最低優先級OB銷毀舊池創建新池-->runloop將退出-->最低優先級OB銷毀新池-->線程(銷毀))

線程剛創建時並沒有runloop,如果你不主動去獲取,那麽一直都不會有。

耗時操作可以放在分線程中進行,結束後回到主線程

利用runLoop加載高清大圖