React Native 交互管理器InteractionManager

一個能夠提高用戶體驗和交互效果的模塊InteractionMnager(交互管理器)es6

1、基本內容

使用InteractionManager可讓一些耗時的任務在交互操做或者動畫完成以後進行執行,這樣使用能夠保證咱們的JavaScript的動畫效果能夠平滑流暢的執行。能夠大大提高用戶體驗。好比:導航的轉場動畫web

對大多數React Native應用來講,業務邏輯是運行在JavaScript線程上的。這是React應用所在的線程,也是發生API調用,以及處理觸摸事件等操做的線程。更新數據到原生支持的視圖是批量進行的,而且在事件循環每進行一次的時候被髮送到原生端,這一步一般會在一幀時間結束以前處理完(若是一切順利的話)。若是JavaScript線程有一幀沒有及時響應,就被認爲發生了一次丟幀。 例如,你在一個複雜應用的根組件上調用了this.setState,從而致使一次開銷很大的子組件樹的重繪,可想而知,這可能會花費200ms也就是整整12幀的丟失。此時,任何由JavaScript控制的動畫都會卡住。只要卡頓超過100ms,用戶就會明顯的感受到。後端

屬性方法瀏覽器

runAfterInteractions(task)  靜態方法,在用戶交互和動畫結束之後執行任務
 
createInteractionHandle() 靜態方法,建立一個句柄(處理器),通知管理器,某個動畫或者交互開始了  

clearInteractionHandle(handler:Handle)  靜態方法,進行清除句柄,通知管理器,某個動畫或者交互結束了。 
 
setDeadline(deadline:number) 靜態方法, 設置延遲時間,該會調用setTimeout方法掛起而且阻塞全部沒有完成的任務,而後在eventLoopRunningTime到設定的延遲時間後,而後執行setImmediate方法進行批量執行任務  

Events:CallExpression  

addListener:CallExpression

在應用開發中咱們能夠以下進行執行任務異步

InteractionManager.runAfterInteractions(() => {
   //執行耗時的同步任務
 
});

該模塊和其餘相關的調度方法對比:函數

requestAnimationFrame():執行控制動畫效果的代碼
setImmediate/setTimeout():設置延遲執行任務的時間,該可能會影響到正在執行的動畫
runAfterInteractions():延遲執行任務,該不會影響到正在執行的動畫效果
觸摸系統中的單點或者多點觸控都是交互動做,耗時任務會在這些觸摸交互動做執行完成以後或者取消之後回調runAfterInteractions()方法進行執行。oop

InteractionManager也容許應用在動畫開始的時候經過createInteractionHandle()方法註冊動畫生成一個句柄,在結束的時候清除該句柄。fetch

var handle = InteractionManager.createInteractionHandle();
 
//執行動畫 (`runAfterInteractions` tasks are queued)
 
//動畫執行結束
 
InteractionManager.clearInteractionHandle(handle);
 
//動畫清除以後,開始直接runAfterInteractions中的任務

runAfterInteractions任務也能夠接收一個普通的回調函數或者一個帶有gen方法而且返回一個Promise的PromiseTask對象。若是參數是PromiseTask對象,那麼任務是異步執行的,也會阻塞。該會等着當前任務執行完畢之後才能執行下一個任務。動畫

默認狀況下,隊列任務會一次性在setImmediate方法中批量執行。若是你經過setDeadline方法設置一個時間值,那麼任務會在延遲該設定值時間進行執行。這時候會調用setTimeout方法進行掛起任務而且阻塞其餘任務的執行。這樣能夠給觸摸交互等操做留出時間更好的相應用戶操做this

具體使用

InteractionManager.runAfterInteractions(() => {
    //執行耗時的同步任務
    navigate("Redeem", { title: "積分兌換" });
})

或者

constructor(props) {
    super(props);
    this.state = {
        renderPlaceholderOnly: true
    }
}
render(){
    if (this.state.renderPlaceholderOnly) {
        // Toast.loading("加載中...", 1);
       return self._renderPlaceholderView();
    }
    return(
    .....
    )
}
componentDidMount = () => {
    InteractionManager.runAfterInteractions(() => {
        this.setState({ renderPlaceholderOnly: false });
    });
        
};

2、定時器

定時器是一個應用中很是重要的部分。React Native實現了和瀏覽器一致的定時器Timer

提供以下方法

setTimeout, clearTimeout
setInterval, clearInterval
setImmediate, clearImmediate
requestAnimationFrame, cancelAnimationFrame

setTimeout (fn, 1000) 和 setInterval (fn,1000)

和web中的意思同樣,前者表示延遲1000毫秒後執行 fn 方法 ,後者表示每隔1000毫秒執行 fn 方法。

requestAnimationFrame(fn)和setTimeout(fn, 0)不一樣,

前者會在每幀刷新以後執行一次,然後者則會盡量快的執行(在iPhone5S上有可能每秒1000次以上)。

setImmediate則會在當前JavaScript執行塊結束的時候執行,就在將要發送批量響應數據到原生以前。注意若是你在setImmediate的回調函數中又執行了setImmediate,它會緊接着馬上執行,而不會在調用以前等待原生代碼。

Promise的實現就使用了setImmediate來執行異步調用。

注意點:

一、定時器功能比較簡單,注意在es6中使用時,需銘記在unmount組件時清除(clearTimeout/clearInterval)全部用到的定時器。

二、可使用定時器實現一些普通功能:如短信倒計時等

三、對於一些須要延遲執行的特殊場景也可使用Timer,譬如:目前RN提供的fetch是沒有提供設置超時時間的,若是客戶端請求後端的一個接口,接口超時了(後端服務設置的超時時間爲10s),那麼RN界面就一直loading,也不能aborded。那麼這時候咱們就能夠巧妙的使用計時器,若是客戶端發出的Request,時間大於某個值(5秒),那麼咱們直接認爲請求失敗。

四、今天還發現一個使用setTimeout的場景,在列表頁加載下一頁的時候,若是接口響應很快,就不會出現loading的效果,這個時候爲了有loading的效果,設置一個500毫秒的延時

相關文章
相關標籤/搜索