React-Native之Android:導入原生模塊

?前提是用react-native init 工程名 已經初始化好一個可以正常運行的RN工程(檢驗標準是在手機上可以正常運行)。

下面的步驟是在RN0.17版本的,0.18版本后也是可以的,由于官方進一步封裝,具體步驟可能略有不同。

一、導入Android原生模塊的步驟

步驟1.新建java類繼承ReactContextBaseJavaModule.

public class MyToastModule extends ReactContextBaseJavaModule

必須復寫getName方法,return后跟的是JS里要調用的名字(可不同于類名)。

public String getName() {

return "MyToastAndroid";

}

定義要被JS使用的方法,要加上注解@ReactMethod

@ReactMethod

public void show(){

Toast.makeText(getReactApplicationContext(),"hello",Toast.LENGTH_LONG).show();

}

步驟2.新建類實現ReactPackage接口

public class MyReactPackage? implements ReactPackage

有三個方法需要實現:createNativeModeule,createJSModules,createViewManagers.這三個方法都返回list,

要注意一點是雖然默認返回null,但這樣寫編譯時會出錯,要改寫成返回空集合,一般寫成

return Collections.emptyList();

此時需要在createNativeModeule里,返回帶有上面module的集合

@Override

public List createNativeModules(ReactApplicationContext reactContext) {

return Arrays.asList(

new MyToastModule(reactContext)

);

}

步驟3.在MainActivity里(在RN工程里是自動生成的入口activity),添加上面的自定義的ReactPackage

mReactInstanceManager = ReactInstanceManager.builder()

。。。。//省略其他代碼

.addPackage(new MainReactPackage())

.addPackage(new MyReactPackage())

。。。。//省略其他代碼

步驟4.在JS里調用剛才的原生模塊

React.NativeModules.MyToastAndroid.show();

二、上面是最簡單的一種調用,基本步驟是不變的,接下來是在上面基礎上多了點東西的調用。

1.在JS里調用帶參數的原生模塊里的方法

將上面的MyToastModule類里的show方法改為

@ReactMethod

public void show(String message,int dur){

Toast.makeText(getReactApplicationContext(),message,dur).show();

}

在JS里調用為

React.NativeModules.MyToastAndroid.show("hello",1);

2.在JS里調用原生模塊里的預設參數

在MyToastModule的Java類里復寫方法getConstants,此方法返回了需要導出給JavaScript使用的常量

@Override? ? ? ? public Map getConstants() {? ? final Map constants = new HashMap<>();? ? ? ? ? ? constants.put("HAHA", Toast.LENGTH_SHORT);? ? ? ? ? ? constants.put("LONG", Toast.LENGTH_LONG);

return constants;? ? ? ? }

在JS里調用為

React.NativeModules.MyToastAndroid.show("hellohaha",React.NativeModules.MyToastAndroid.HAHA);

3.將原生模塊封裝成一個JS模塊,以便省下每次都從NativeModules中獲取對應模塊的步驟,從JS端訪問更為方便。

新建名為MyToastAndroidJS的JS文件,文件里內容為

'use strict'

var {NativeModules} = require('react-native');

module.exports=NativeModules.MyToastAndroid;

在其他JS代碼或文件中可以這樣調用,

var MyToastAndroidLOL = require('./MyToastAndroidJS');//此處確保按文件路徑可以被查找到

MyToastAndroidLOL.show('haha JSModule',MyToastAndroidLOL.HAHA);

三、回調函數

上面全是JS調用原生模塊里的方法,有參或無參,但原生模塊只是被調用,沒有反饋回來數據,下面是回調使用說明。(此處承接上面的3)

1.使用Callback回調

在MyToastAndroid中添加方法showAll。在showAll的參數中的callback是com.facebook.react.bridge.Callback,注意別導錯包了。

@ReactMethod

public void showAll(int a,int b,Callback erroCallBack,Callback successCallback){

try{

int c=a/b;

successCallback.invoke(a,b);

}catch(Exception e){

erroCallBack.invoke(e.getMessage());

}

}

在JS中調用showAll方法

MyToastAndroidJJ.showAll(

1,2,

(msg) => {console.log(msg)},

(x,y) => {console.log(x+':'+y)}

);

運行后logcat上會打印出1:2,

當是

MyToastAndroidJJ.showAll(

1,0,

(msg) => {console.log(msg)},

(x,y) => {console.log(x+':'+y)}

);

運行后logcat上會打印出 divide by zero等異常信息。

這樣就實現了原生模塊向JS傳遞數據,并且其中有很大的自由度供調用實現。但要注意showAll里的參數個數在被JS調用時是要一一對應的,在MyToastAndroid中定義了幾個參數就要在JS中調用時提供幾個參數。

2.使用Promise回調

在MyToastAndroid中添加方法showB

@ReactMethod

public void showB(int a,int b,Promise promise){

try{

int c=a/b;

promise.resolve(a+b);

}catch(Exception e){

promise.reject("test:"+e.getMessage());

}

}

在JS中,聲明一個方法

showBInJS: async function (){

try{

var c = await MyToastAndroidJJ.showB(1,2);

console.log("test:"+c);

}catch(e){

console.log(e);

}

},

在JS中調用

this.showBInJS();

在log中會打印出 test:3。

把上面聲明中的2改為0,保存然后Reload JS。

在log中會打印出 test:divide by zero 等異常信息。

上面是返回一個參數,下面是可以返回多個參數的方式(不唯一)

在MyToastAndroid中改寫方法showB

@ReactMethod

public void showB(int a,int b,Promise promise){

try{

int c=a/b;

WritableMap map = Arguments.createMap();

map.putInt("haha",a);

map.putInt("hehe",b);

promise.resolve(map);

}catch(Exception e){

promise.reject("fyp:"+e.getMessage());

}

}

在JS中改寫showBInJS的聲明

showBInJS: async function (){

try{

var {haha,hehe} = await MyToastAndroidJJ.showB(1,2);

console.log("test:"+haha+":"+hehe);

}catch(e){

console.log(e);

}

},

調用不變。

重新react-native run-android,在log里會打印出 test:1:2。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容