RN 與原生通訊(Android篇)
RN
呼叫android
程式碼大致分為以下幾個步驟:
1、用android studio
開啟一個已經建立好的RN
專案;
2、建立一個類CommonModule
繼承自ReactContextBaseJavaModule
,並重寫getName()
方法,在該類中我們要暴露一些方法供RN
呼叫;
class CommonModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { } 複製程式碼
-
實現
getName()
方法,改方法用來返回RN
程式碼需要尋找的類的名稱;
override fun getName(): String { // 一定要有名字 RN程式碼要通過名字來呼叫該類的方法 return "CommonModule" } 複製程式碼
-
建立暴露給
RN
呼叫的方法,並用@ReactMethod
註解修飾;
/** * 加上 @ReactMethod 註解是為了暴露給RN呼叫的方法; * * 方法不能返回值,因為被呼叫的原生程式碼是非同步的,原生程式碼執行結束之後只能通過回撥函式或者傳送訊息給RN */ @ReactMethod fun rnCallNative(msg: String) { // 這個方法是說彈出一個彈窗到介面 Toast.makeText(reactContext, msg, Toast.LENGTH_LONG).show() } 複製程式碼
3、建立類CommonPackage
實現介面ReactPackage
包管理器,並把第2步中建立好的CommonModule
類新增進來;
class CommonPackage : ReactPackage { override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { val list = ArrayList<NativeModule>() list.add(CommonModule(reactContext)) return list } override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { return emptyList() } } 複製程式碼
4、將建立好的CommonPackage
包管理器新增到ReactPackage
列表中;也就是在ReactNativeActivity
中的onCreate
方法中新增:
class ReactNativeActivity : AppCompatActivity(), DefaultHardwareBackBtnHandler { private var mReactRootView: ReactRootView? = null private var mReactInstanceManager: ReactInstanceManager? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val list = mutableListOf<ReactPackage>() list.add(MainReactPackage()) // 預設 list.add(CommonPackage()) // 自定義Package mReactRootView = ReactRootView(this) mReactInstanceManager = ReactInstanceManager.builder() .setApplication(application) .setCurrentActivity(this) //.setBundleAssetName("index.android.bundle") .setJSBundleFile(CodePush.getJSBundleFile())// ! 此處為codePush載入JsBundle方式,預設為.setBundleAssetName("index.android.bundle") .setJSMainModulePath("index") // ! 注意這裡的index指向入口的js檔案 //.addPackage(MainReactPackage()) .addPackages(list) // ! 此處為擴充套件Packages,預設為.addPackage(new MainReactPackage()) .setUseDeveloperSupport(BuildConfig.DEBUG) .setInitialLifecycleState(LifecycleState.RESUMED) .build() // 注意這裡的 rn_sample 必須對應“index.js”中的 “AppRegistry.registerComponent()”的第一個引數 mReactRootView?.startReactApplication(mReactInstanceManager, "rn_sample", null) setContentView(mReactRootView) } ... } 複製程式碼
5、在RN
程式碼中用NativeModules
元件去呼叫原生模組;
- 匯入元件,設定方法呼叫原生方法;
import {Alert, Button, NativeModules, StyleSheet, View} from 'react-native'; const commonModule = NativeModules.CommonModule; function callAndroid() { commonModule.rnCallNative('RN 呼叫 Android 原生~~'); } 複製程式碼
-
在
render
方法裡設定button
的點選事件直接呼叫自定義方法callAndroid
即可;
render() { return ( <View style={styles.container}> <Button title='call_android' onPress={callAndroid}/> </View> ); } 複製程式碼
到此,基本的RN
呼叫安卓原生程式碼的方式就得以實現。
二、RN 用 Promise 機制與安卓原生程式碼通訊
在原生程式碼CommonModule
類中建立橋接方法,當橋接的方法最後一個引數是Promise
物件,那麼該方法就會返回一個JS
的Promise
物件給對應的JS
方法。
1、首先需要在CommonModule
中定義一個暴露給RN
的方法,並且要用@ReactMethod
標識;
@ReactMethod fun rnCallNativePromise(msg: String, promise: Promise) { Toast.makeText(reactContext, msg, Toast.LENGTH_LONG).show() val componentName = name promise.resolve(componentName) } 複製程式碼
2、在RN
程式碼中也是需要用NativeModules
元件呼叫原生模組;
import {Alert, Button, NativeModules, StyleSheet, View} from 'react-native'; const commonModule = NativeModules.CommonModule;function callAndroidPromise() { commonModule.rnCallNativePromise('RN Promise 呼叫 Android 原生~~') .then((msg) => { Alert.alert('promise 收到訊息', msg) console.log("promise 收到訊息", msg) }) .catch((error) => { console.log(error) }) } 複製程式碼
render() { return ( <View style={styles.container}> <Button title='call_android' onPress={callAndroid}/> <Button title='call_android_promise' onPress={callAndroidPromise}/> </View> ); } 複製程式碼
三、RN 用 callback 回撥方式與安卓原生程式碼通訊
1、 同樣也是按照上面的方式,在原生模組中暴露一個橋接的方法給RN
呼叫,引數傳入一個成功的回撥和一個失敗的回撥;
@ReactMethod fun rnCallNativeCallback(success: Callback, error: Callback) { try { success.invoke(100, 200) } catch (e: Exception) { error.invoke(e.message) } } 複製程式碼
2、在RN
程式碼中也是需要用NativeModules
元件呼叫原生模組;
import {Alert, Button, NativeModules, StyleSheet, View} from 'react-native'; const commonModule = NativeModules.CommonModule;function callAndroidCallback() { commonModule.rnCallNativeCallback((x, y) => { Alert.alert('callback 收到訊息', x + ',' + y) console.log('callback 收到訊息', x, y) }, (error) => { console.log(error) }) } 複製程式碼
render() { return ( <View style={styles.container}> <Button title='call_android' onPress={callAndroid}/> <Button title='call_android_promise' onPress={callAndroidPromise}/> <Button title='call_android_callback' onPress={callAndroidCallback}/> </View> ); } 複製程式碼
最後,RN與安卓原生之間的通訊方式已經介紹完了,如有不對的地方,歡迎指正~~
完整的專案地址:github.com/iceCola7/rn…