正如上篇文章[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è)class
MyReactPackager
,實(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
,需要在MainActivity
的getPackages
中注冊(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)目,最終效果圖如下:
本文的源碼地址:Demo2
下一篇文章會(huì)介紹JS調(diào)用原生模塊的高級(jí)用法,敬請(qǐng)期待~