[React Native]原生模塊(上)

正如上篇文章[React Native]移植原生Android項(xiàng)目中提到,ReactNative目前更多的是用于在原生App中加入一個(gè)新的模塊。那么,此時(shí)如果這個(gè)ReactNative模塊需要使用到一些原生模塊的功能,比如訪問(wèn)平臺(tái)的API;或者你要復(fù)用現(xiàn)成的Java代碼;又或者使用Java已經(jīng)成熟的第三方Library,那么這篇文章會(huì)一步步告訴你,如何去調(diào)用一個(gè)已經(jīng)封裝好的Android原生代碼。

實(shí)際上,正如上篇文章[React Native]移植原生Android項(xiàng)目中提到,目前更多的還是使用React來(lái)做V的工作,那么諸如網(wǎng)絡(luò)請(qǐng)求之類還是通過(guò)在ReactNative模塊中調(diào)用原生已經(jīng)封裝好的庫(kù)來(lái)實(shí)現(xiàn)(據(jù)說(shuō)餓了么目前就是這個(gè)方案~)

為了更好的理解,本文演示如何在ReactNative中使用Android平臺(tái)的Toast功能。

  • 步驟一:新建ReactNative項(xiàng)目

    使用下面的命令新建一個(gè)ReactNative項(xiàng)目,確保你的環(huán)境已經(jīng)配置正確,有問(wèn)題可以參考[React Native]入門(mén)篇
    react-native init Demo2
    讓我們運(yùn)行下新建的項(xiàng)目,效果如下

    Paste_Image.png

  • 步驟二:新建原生模塊

    用AS開(kāi)發(fā)工具打開(kāi)Demo2目錄下的android項(xiàng)目,新建一個(gè)classToastModule繼承ReactContextBaseJavaModule,我們的目標(biāo)是在JS中這樣寫(xiě)ToastAndroid.show("Test Toast",ToastAndroid.SHORT),來(lái)顯示一個(gè)Toast。
    public class ToastModule extends ReactContextBaseJavaModule {
    public ToastModule(ReactApplicationContext reactContext) {
    super(reactContext);
    }
    }
    ReactContextBaseJavaModule要求實(shí)現(xiàn)getName方法,該方法返回一個(gè)String,表示模塊的名稱,這里返回ToastAndroid。
    @Override
    public String getName() {
    return "ToastAndroid";
    }
    一個(gè)可選的方法getConstants,用來(lái)封裝常量給JS模塊使用,比如我們將要用到的常量ToastAndroid.SHORT。

    @Override
    public Map<String, Object> getConstants() {
      final Map<String, Object> constants = new HashMap<>();
      constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
      constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
      return constants;
    }
    

Java中的方法需要導(dǎo)出才能給JS使用,要導(dǎo)出Java方法,需要使用@ReactMethod來(lái)注解,且方法的返回值只能是void
@ReactMethod
public void show(String message, int duration) {
Toast.makeText(getReactApplicationContext(), message, duration).show();
}
這樣,我們的原生模塊已經(jīng)創(chuàng)建完畢,下面需要注冊(cè)原生模塊了。

  • 步驟三:注冊(cè)原生模塊

    新建一個(gè)classMyReactPackager,實(shí)現(xiàn)ReactPackager接口,我們需要實(shí)現(xiàn)createNativeModules方法,該方法返回所有需要被加載的原生模塊。
    public class MyReactPackager implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> viewManagers = new ArrayList<>();
    viewManagers.add(new ToastModule(reactContext));
    return viewManagers;
    }

      @Override
      public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList(); // 返回null會(huì)報(bào)錯(cuò)
      }
    
      @Override
      public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList(); // 返回null會(huì)報(bào)錯(cuò)
      }
    }
    

我們新建的MyReactPackager,需要在MainActivitygetPackages中注冊(cè)并返回。

  /**
   * A list of packages used by the app. If the app uses additional views
   * or modules besides the default ones, add more packages here.
   */
  @Override
  protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new MyReactPackager() // 這是我們自定義的ReactPackager
    );
  }

到此原生模塊的工作已經(jīng)告一段落,下面讓我們看下如下在ReactNative中調(diào)用我們的原生模塊。

  • 步驟四:使用原生模塊
    打開(kāi)index.android.js文件,在render方法中用TouchableOpacity封裝一個(gè)可以點(diǎn)擊的視圖Text,文本內(nèi)容為Click to show native Toast。

    render() {
      return (
        <View style={styles.container}>
          <TouchableOpacity onPress={this.onPressButton}>
            <Text style={styles.instructions}>
            Click to show native Toast
            </Text>
          </TouchableOpacity>
        </View>
      );
    }
    

JS文件中,引入我們步驟二中新建的原生模塊ToastAndroid

  var ToastAndroid = require('ToastAndroid');

TouchableOpacity點(diǎn)擊方法為onPressButton,它會(huì)調(diào)用原生模塊導(dǎo)出的show方法。

  onPressButton() {
    ToastAndroid.show('Android Toast', ToastAndroid.SHORT);
  }

讓我們運(yùn)行下項(xiàng)目,最終效果圖如下:

device-2016-05-19-221758_0-24.gif

本文的源碼地址Demo2

下一篇文章會(huì)介紹JS調(diào)用原生模塊的高級(jí)用法,敬請(qǐng)期待~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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