[React Native]原生模塊(下)

上一篇文章[React Native]原生模塊(上)中我們介紹了原生模塊的基本用法魏身,本篇文章將介紹原生模塊的高級(jí)用法—ReactNative與原生模塊的通信方式老虫。

由于本文涉及到很多React方面的知識(shí),比如state企蹭、生命周期等,沒有接觸過的同學(xué)建議首先閱讀下阮一峰老師的React入門實(shí)例教程

通信方式總共分為以下三種:

  • Callback
  • Promise
  • Event

本文將演示原生模塊使用Thread異步執(zhí)行方法后回調(diào)JS模塊,并在界面上顯示出線程的名字和執(zhí)行時(shí)間竖配,效果圖如下

device-2016-05-26-214323_0-87.gif

首先,按照上一篇文章[React Native]原生模塊(上)的步驟
1里逆、新建一個(gè)ReactNative項(xiàng)目
2甚颂、并創(chuàng)建名稱為NativeAndroid的原生模塊
3、最后完成他的注冊(cè)工作
此時(shí)漏策,NativeAndroid的代碼如下

public class NativeModule extends ReactContextBaseJavaModule {
  ReactApplicationContext mReactContext;
  public NativeModule(ReactApplicationContext reactContext) {
      super(reactContext);
      mReactContext = reactContext;
  }

  @Override
  public String getName() {
      return "NativeAndroid";
  } 
}

4圾另、在index.android.js中用TouchableOpacity包裹三個(gè)可點(diǎn)擊的ViewCallbackPromise诸衔、Event

render() {
  return (
    <View style={styles.container}>
      <TouchableOpacity onPress={()=>{
        
        }}>
        <Text style={styles.welcome}>
          Callback
        </Text>
      </TouchableOpacity>
    
      <TouchableOpacity onPress={()=>{
        
        }}>
        <Text style={styles.welcome}>
          Promise
        </Text>
      </TouchableOpacity>
    
      <TouchableOpacity onPress={()=>{
        
        }}>
        <Text style={styles.welcome}>
          Event
        </Text>
      </TouchableOpacity>
    </View>
  );
}

5盯漂、在index.android.js中新建一個(gè)stateresult

簡單理解就是一個(gè)特殊的屬性,一旦修改它的值笨农,會(huì)觸發(fā)render方法就缆,這樣頁面就得到刷新了。對(duì)這個(gè)用法不了解的同學(xué)谒亦,可以參考阮一峰老師的React入門實(shí)例教程

// es6語法竭宰,如果使用React.createClass則使用getInitialState
constructor () {
  super();
  this.state = {
    result: ''
  }
}

render() {
  return (
    <View style={styles.container}>
      // 此處代碼省略若干行
      <Text style={styles.instructions}>
        {this.state.result}
      </Text>
    </View>
  );
}

準(zhǔn)備步驟到此結(jié)束了。

下面份招,我們分別介紹三種實(shí)現(xiàn)方式

  • Callback

回調(diào)函數(shù)切揭,對(duì)應(yīng)JS中的function

1、在NativeModule中新建testCallback方法 锁摔,包含一個(gè)參數(shù)Callback(對(duì)應(yīng)JSfunction

  @ReactMethod
  public void testCallback(final Callback callback)
  {
      new Thread(new Runnable() {
          @Override
          public void run() {
              try {
                  Thread.sleep(3000);
                  callback.invoke("Callback: " + Thread.currentThread().getName() + " has slept 3 ms.");
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
      }).start();
  }

2廓旬、在CallbackonPresss方法中調(diào)用testCallback方法

  <TouchableOpacity onPress={()=>{
    NativeAndroid.testCallback((msg)=>{
          this.setState({result: msg});
        });
    }}>
    <Text style={styles.welcome}>
        Callback
    </Text>
  </TouchableOpacity>

這里給testCallback方法傳遞了一個(gè)箭頭函數(shù),并將返回值msg賦值給result谐腰,然后會(huì)觸發(fā)render方法刷新界面孕豹。

  • Promise

這里涉及到ES7標(biāo)準(zhǔn)的JS語法,需要配合async/await來使用怔蚌。橋接的原生方法的最后一個(gè)參數(shù)為Promise

1巩步、在NativeModule中新建testPromise方法 ,包含一個(gè)參數(shù)Promise(當(dāng)然桦踊,你也可以同時(shí)傳遞其他參數(shù))

  @ReactMethod
  public void testPromise(final Promise promise)
  {
      new Thread(new Runnable() {
          @Override
          public void run() {
              try {
                  Thread.sleep(3000);
                  WritableMap map = Arguments.createMap();
                  map.putString("msg", "Promise: " + Thread.currentThread().getName() + " has slept 3 ms.");
                  promise.resolve(map);
              } catch (InterruptedException e) {
                  promise.reject("InterruptedException", e);
              }
          }
      }).start();
  }

這里椅野,使用promise.resolve來傳遞一個(gè)WritableMap,使用promise.reject來傳遞錯(cuò)誤信息

WritableMap類似一個(gè)字典,用來包裝多個(gè)輸出參數(shù)給JS模塊

2竟闪、在index.android.js文件的class新建一個(gè)方法promise离福,方法需要使用async來修飾

  // es7語法,Promise必須配合async使用
  async promise()
  {
    try {
      var {
        msg
      } = await NativeAndroid.testPromise();
      this.setState({result: msg});
    } catch (error) {
      console.log(error);
    }
  }

這里炼蛤,var {msg} = await NativeAndroid.testPromise();中的msg對(duì)應(yīng)原生方法public void testPromise(final Promise promise)的語句promise.resolve(map);map傳遞的參數(shù)msg妖爷,最后使用this.setState({result: msg});來刷新界面

3、在PromiseonPress方法中調(diào)用promise方法

  <TouchableOpacity onPress={()=>{
      this.promise();
    }}>
    <Text style={styles.welcome}>
      Promise
    </Text>
  </TouchableOpacity>
  • Event

1理朋、原生模塊可以在沒有被調(diào)用的情況下往JavaScript發(fā)送事件通知絮识。最簡單的辦法就是通過RCTDeviceEventEmitter,這可以通過ReactContext來獲得對(duì)應(yīng)的引用嗽上,像這樣:
mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("事件名稱", Object);

2次舌、原生模塊可以主動(dòng)通知JS模塊,這里為了簡單起見兽愤,還是通過JS觸發(fā)原生方法彼念,原生方法再發(fā)送事件到JS模塊

1、在NativeModule中新建testEvent方法

  /**
   * 發(fā)送事件到JS
   * [為了簡單演示浅萧,從JS調(diào)用此方法再發(fā)送事件到JS]
   */
  @ReactMethod
  public void testEvent()
  {
      new Thread(new Runnable() {
          @Override
          public void run() {
              try {
                  Thread.sleep(3000);
                  mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                        .emit("testEvent", "Event: " + Thread.currentThread().getName() + " has slept 3 ms.");
              } catch (InterruptedException e) {
              }
          }
      }).start();
  }

2逐沙、在JS模塊組件Component的生命周期函數(shù)componentWillMount中注冊(cè)事件監(jiān)聽,并在收到通知后刷新界面

  componentWillMount()
  {
     DeviceEventEmitter.addListener('testEvent', (msg) => {
       this.setState({result: msg});
     });
  }

當(dāng)然洼畅,你需要引入DeviceEventEmitter

  import {
    // ...省略若干行代碼
    DeviceEventEmitter
  } from 'react-native';

3吩案、在EventonPress方法中調(diào)用testEvent方法

  <TouchableOpacity onPress={()=>{
        NativeAndroid.testEvent();
      }}>
      <Text style={styles.welcome}>
        Event
      </Text>
  </TouchableOpacity>

最后,讓我們?cè)俅慰聪伦罱K效果圖

device-2016-05-26-214323_0-87.gif

本文的源碼地址Demo3

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末土思,一起剝皮案震驚了整個(gè)濱河市务热,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌己儒,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捆毫,死亡現(xiàn)場(chǎng)離奇詭異闪湾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绩卤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門途样,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人濒憋,你說我怎么就攤上這事何暇。” “怎么了凛驮?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵裆站,是天一觀的道長。 經(jīng)常有香客問我,道長宏胯,這世上最難降的妖魔是什么羽嫡? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮肩袍,結(jié)果婚禮上杭棵,老公的妹妹穿的比我還像新娘。我一直安慰自己氛赐,他們只是感情好魂爪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艰管,像睡著了一般甫窟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蛙婴,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天粗井,我揣著相機(jī)與錄音,去河邊找鬼街图。 笑死浇衬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的餐济。 我是一名探鬼主播耘擂,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼絮姆!你這毒婦竟也來了醉冤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤篙悯,失蹤者是張志新(化名)和其女友劉穎蚁阳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸽照,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡螺捐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矮燎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片定血。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖诞外,靈堂內(nèi)的尸體忽然破棺而出澜沟,到底是詐尸還是另有隱情,我是刑警寧澤峡谊,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布茫虽,位于F島的核電站刊苍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏席噩。R本人自食惡果不足惜班缰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望悼枢。 院中可真熱鬧埠忘,春花似錦、人聲如沸馒索。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绰上。三九已至旨怠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜈块,已是汗流浹背鉴腻。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留百揭,地道東北人爽哎。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像器一,于是被迫代替她去往敵國和親课锌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容