Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 《React-Native系列》18、 RN之定時器Timer

《React-Native系列》18、 RN之定時器Timer

編輯:關於Android編程

在web開發中,我們通常需要使用定時器功能,使用setTimeout和setInterval函數。

那麼在ReactNative中,是否也提供了定時器的功能呢? 答案是肯定的。

我們還是先看看官網怎麼說的。

定時器是一個應用中非常重要的部分。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來執行異步調用。

InteractionManager(交互管理器)
原生應用感覺如此流暢的一個重要原因就是在互動和動畫的過程中避免繁重的操作。在React Native裡,我們目前受到限制,因為我們只有一個JavaScript執行線程。不過你可以用InteractionManager來確保在執行繁重工作之前所有的交互和動畫都已經處理完畢。
應用可以通過以下代碼來安排一個任務,使其在交互結束之後執行:

InteractionManager.runAfterInteractions(() => {
   // ...需要長時間同步執行的任務...
});

我們來把它和之前的幾個任務安排方法對比一下:
requestAnimationFrame(): 用來執行在一段時間內控制視圖動畫的代碼
setImmediate/setTimeout/setInterval(): 在稍後執行代碼。注意這有可能會延遲當前正在進行的動畫。
runAfterInteractions(): 在稍後執行代碼,不會延遲當前進行的動畫。
觸摸處理系統會把一個或多個進行中的觸摸操作認定為'交互',並且會將runAfterInteractions()的回調函數延遲執行,直到所有的觸摸操作都結束或取消了。
InteractionManager還允許應用注冊動畫,在動畫開始時創建一個交互“句柄”,然後在結束的時候清除它。

var handle = InteractionManager.createInteractionHandle();
// 執行動畫... (`runAfterInteractions`中的任務現在開始排隊等候)
// 在動畫完成之後
InteractionManager.clearInteractionHandle(handle);
// 在所有句柄都清除之後,現在開始依序執行隊列中的任務

TimerMixin
我們發現很多React Native應用發生致命錯誤(閃退)是與計時器有關。具體來說,是在某個組件被卸載(unmount)之後,計時器卻仍然被激活。為了解決這個問題,我們引入了TimerMixin。如果你在組件中引入TimerMixin,就可以把你原本的setTimeout(fn, 500)改為this.setTimeout(fn, 500)(只需要在前面加上this.),然後當你的組件卸載時,所有的計時器事件也會被正確的清除。

這個庫並沒有跟著React Native一起發布。你需要在項目文件夾下輸入npm i react-timer-mixin --save來單獨安裝它。
 

var TimerMixin = require('react-timer-mixin');

var Component = React.createClass({
  mixins: [TimerMixin],
  componentDidMount: function() {
    this.setTimeout(
      () => { console.log('這樣我就不會導致內存洩露!'); },
      500
    );
  }
});
我們強烈建議您使用react-timer-mixin提供的this.setTimeout(...)來代替setTimeout(...)。這可以規避許多難以排查的BUG。


譯注:Mixin屬於ES5語法,對於ES6代碼來說,無法直接使用Mixin。

如果你的項目是用ES6代碼編寫,同時又使用了計時器,那麼你只需銘記在unmount組件時清除(clearTimeout/clearInterval)所有用到的定時器。

那麼也可以實現和TimerMixin同樣的效果。例如:
 

import React,{
  Component
} from 'react-native';


export default class Hello extends Component {
  componentDidMount() {
    this.timer = setTimeout(
      () => { console.log('把一個定時器的引用掛在this上'); },
      500
    );
  }
  componentWillUnmount() {
    // 如果存在this.timer,則使用clearTimeout清空。
    // 如果你使用多個timer,那麼用多個變量,或者用個數組來保存引用,然後逐個clear
    this.timer && clearTimeout(this.timer);
  }
};

注意點:

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

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

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

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

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved