RN 與原生通訊(Android篇)

1、RN 調用安卓代碼(簡單的實現方式)

RN 調用 android 代碼大體分爲如下幾個步驟:react

一、用android studio 打開一個已經建立好的 RN 項目;android

二、建立一個類 CommonModule 繼承自 ReactContextBaseJavaModule ,並重寫 getName() 方法,在該類中咱們要暴露一些方法供 RN 調用;git

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()
}
複製代碼

三、建立類 CommonPackage 實現接口 ReactPackage 包管理器,並把第2步中建立好的 CommonModule 類添加進來;github

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()
    }
}
複製代碼

四、將建立好的 CommonPackage 包管理器添加到 ReactPackage 列表中;也就是在 ReactNativeActivity 中的 onCreate 方法中添加:react-native

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)
    }
	...
}
複製代碼

五、在 RN 代碼中用 NativeModules 組件去調用原生模塊;promise

  • 導入組件,設置方法調用原生方法;
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 調用安卓原生代碼的方式就得以實現。bash

2、RN 用 Promise 機制與安卓原生代碼通訊

在原生代碼 CommonModule 類中建立橋接方法,當橋接的方法最後一個參數是 Promise 對象,那麼該方法就會返回一個JSPromise 對象給對應的 JS 方法。app

一、首先須要在 CommonModule 中定義一個暴露給 RN 的方法,而且要用 @ReactMethod 標識;異步

@ReactMethod
fun rnCallNativePromise(msg: String, promise: Promise) {
    Toast.makeText(reactContext, msg, Toast.LENGTH_LONG).show()
    val componentName = name
    promise.resolve(componentName)
}
複製代碼

二、在 RN 代碼中也是須要用 NativeModules 組件調用原生模塊;ide

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>
    );
}
複製代碼

3、RN 用 callback 回調方式與安卓原生代碼通訊

一、 一樣也是按照上面的方式,在原生模塊中暴露一個橋接的方法給 RN 調用,參數傳入一個成功的回調和一個失敗的回調;

@ReactMethod
fun rnCallNativeCallback(success: Callback, error: Callback) {
    try {
        success.invoke(100, 200)
    } catch (e: Exception) {
        error.invoke(e.message)
    }
}
複製代碼

二、在 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…

相關文章
相關標籤/搜索