美文网首页
ReactNative原生集成-Android

ReactNative原生集成-Android

作者: 玄策 | 来源:发表于2017-12-19 11:50 被阅读223次

    目录

    • 1)搭建-原生集成rn
    • 2)demo-包含搭建过程源码
    • 3)访问原生侧常量
    • 4)访问原生侧方法
      • 4.1)void无返回
      • 4.2)有返回回调
    • 5)原生启动RN
      • 5.1)RN获取Activity传递的Intent数据
      • 5.2)startActivityForResult返回Intent数据给Activity
    • 6)RN启动原生
      • 6.1)Activity获取RN传递的Intent数据
      • 6.2)startActivityForResult返回Intent数据给RN
      • 6.3)原生发送通知给RN
    • 7)UI互嵌
      • 7.1)原生界面内部分使用RN的界面
      • 7.2)RN界面内部分使用原生的界面

    1)搭建-原生集成rn

    • react-native init 工程名
    • copy原Android工程至Rn工程/android中,配置gradle
    • app的gradle中加入
     dependencies {
         ...
         compile "com.facebook.react:react-native:+" // From node_modules.
     }
    
    • 项目gradle中加入
    allprojects {
        repositories {
            ...
            maven {
                // All of React Native (JS, Android binaries) is installed from npm
                url "$rootDir/../node_modules/react-native/android"
            }
        }
        ...
    }
    
    • 配置权限
    <uses-permission android:name="android.permission.INTERNET" />
    <!-开发者菜单 可不用->
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
    
    • 配置Application
    public class MainApplication extends Application implements ReactApplication {
    
        private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
            @Override
            public boolean getUseDeveloperSupport() {
                //Debug模式,这个模式才能在JS里作调试
                return BuildConfig.DEBUG;
            }
    
            @Override
            protected List<ReactPackage> getPackages() {
                //返回带有官方已有的package的集合
                return Arrays.<ReactPackage>asList(
                        new MainReactPackage()
                );
            }
        };
    
        @Override
        public ReactNativeHost getReactNativeHost() {
            return mReactNativeHost;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            SoLoader.init(this, /* native exopackage */ false);
        }
    }
    
    • Android 6.0(API level 23)或更高版本,开发版本中会要求打开悬浮窗(overlay)权限,生产版本则不要求,代码可不用特别配置
    • 新建Activity
    public class FirstReactActivity extends ReactActivity {
    
        @Override
        protected String getMainComponentName() {
            return "FirstReactComponent";  //注册的react组件名,RN里要用到
        }
    }
    
    • 新建RN-Component
    export default class FirstReactComponent extends Component {
      render() {
        return (
          <View style={styles.container}>
            <Text style={styles.welcome}>
              大家好,我是React界面release
            </Text>
          </View>
        );
      }
    }
    
    • 在RN的入口文件处注册此Component,注意所有暴露给原生的Component都需要在入口文件处注册。
      ~/index.android.js
    import FirstReactComponent from './src/FirstReactComponent';
    ...
    //暴露给原生使用
    AppRegistry.registerComponent('FirstReactComponent', () => FirstReactComponent);
    
    • 打开Packager服务
      ~/工程根目录
    npm start
    
    ReactNative原生集成-Android
    • 生产打release包
    //创建keystore并配置gradle
        signingConfigs {
            release {
                storeFile file("/Users/tugaofeng/tgf/study/rn/studyRn_Native/studyRn_Native_keystore")
                storePassword "123456"
                keyAlias "studyRn_Native_keystore"
                keyPassword "123456"
            }
        }
        buildTypes {
            release {
                ...
                signingConfig signingConfigs.release
            }
        }
    //创建assets目录 ./android/app/src/main/assets
    //创建离线bundle和打包本地资源
    react-native bundle --entry-file index.android.js --bundle-output ./android/app/src/main/assets/index.android.bundle --platform android --assets-dest ./android/app/src/main/res/ --dev false
    //打签名包即可
    cd android && ./gradlew assembleRelease
    //进入目录安装apk  ./android/app/build/outputs/apk/release
    adb install app-release.apk 
    

    2)demo

    demo
    Android快照
    RN快照
    • 创建一个原生模块,继承了ReactContextBaseJavaModule的Java类,内部可以实现一些JavaScript所需的功能
    public class MyNativeBridgeModule extends ReactContextBaseJavaModule {
    
        //定义全局回调,RN->原生  startActivityForResult 返回数据给之前的 RNActivity
        private Callback secondActivityOnActivityResultCallback;
        //定义全局rnContext
        private ReactApplicationContext rnContext;
    
        public MyNativeBridgeModule(ReactApplicationContext reactContext) {
            super(reactContext);
            rnContext = reactContext;
            //定义监听 RN->原生  startActivityForResult 返回数据给之前的 RNActivity
            reactContext.addActivityEventListener(mActivityEventListener);
        }
    
        //重写此方法,
        //可在RN端通过React.NativeModules.NativeBridge标记使用此模块
        @Override
        public String getName() {
            return "MyNativeBridgeModule";
        }
    
        //此方法可被RN端访问常量
        @Nullable
        @Override
        public Map<String, Object> getConstants() {
            final Map<String, Object> constants = new HashMap<String, Object>();
            constants.put("Duration_Short", Toast.LENGTH_SHORT);
            constants.put("Duration_Long", Toast.LENGTH_LONG);
            constants.put("Native_Constants_A", "我是Native常量值");
            return constants;
        }
    
        //@ReactMethod 此注解定义与RN端的调用方法
        @ReactMethod
        public void showToast(String msg, int duration) {
            Toast.makeText(getReactApplicationContext(), msg, duration).show();
        }
    
        //方法的返回类型必须为void,跨端访问为异步进行,需要返回值须写回调
        @ReactMethod
        public void testCallBack(String msg, Callback successCB, Callback errorCB) {
            try {
                String result = msg + " ,但我被testCallBack方法修改了";
                successCB.invoke(result);
            } catch (Exception e) {
                errorCB.invoke("异常:" + e.getMessage());
            }
        }
    
        //实例:原生->RN 获取之前Activity传递的数据
        @ReactMethod
        public void getDataFromIntent(Callback successCB, Callback errorCB) {
            try {
                Activity currentActivity = getCurrentActivity();
                String intentString = currentActivity.getIntent().getStringExtra("intentData");
                successCB.invoke(intentString);
            } catch (Exception e) {
                errorCB.invoke("异常:" + e.getMessage());
            }
        }
    
        //实例:原生->RN  startActivityForResult 返回数据给之前的Activity
        @ReactMethod
        public void finishActivityForResult(String msg) {
            Activity currentActivity = getCurrentActivity();
            Intent intent = new Intent();
            intent.putExtra("intentData", msg);
            currentActivity.setResult(Activity.RESULT_OK, intent);
            currentActivity.finish();
        }
    
        //实例: RN->原生  打开新的Activity
        //实际项目中可进行实际封装
        @ReactMethod
        public void startNewActivityByString(String activityName, String data, Callback resultCB) {
            Activity currentActivity = getCurrentActivity();
            //此处采用隐式启动,方便封装。若显示启动,需要反射获取class,或业务层上做kv映射。
            Intent intent = new Intent("com.tgf.studyrn_native_android.SecondActivity");
            //此处采用显示启动,需要反射
    //        Class aimActivity = null;
    //        try {
    //            aimActivity = Class.forName("com.tgf.studyrn_native_android.SecondActivity");
    //        } catch (ClassNotFoundException e) {
    //            e.printStackTrace();
    //        }
    //        Intent intent = new Intent(currentActivity,aimActivity);
    
            //将回调函数赋值给全局变量,以便全局callback在mActivityEventListener中使用
            secondActivityOnActivityResultCallback = resultCB;
            currentActivity.startActivityForResult(intent, 1002);
        }
    
        //实例:RN->原生  startActivityForResult 返回数据给之前的 RNActivity
        //方式一 : Callback回调
        //方式二 : 发送通知
        private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
            @Override
            public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
                switch (requestCode) {
                    case 1002:
                        //方式一 : Callback回调
    //                    try {
    //                        secondActivityOnActivityResultCallback.invoke(intent.getStringExtra("intentData"));
    //                    }catch (Exception e){
    //                    }
                        //方式二 : 发送通知
                        rnContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("notify", intent.getStringExtra("intentData"));
                        break;
                }
            }
        };
    }
    
    • 创建自定义的ReactPackage,并在其中注册第一步创建的原生模块
    public class MyReactPackage implements ReactPackage {
        @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Collections.emptyList();  //return null编译时会出错,要改写成返回空集合
        }
    
        //注册Native模块
        @Override
        public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
            List<NativeModule> modules = new ArrayList<>();
            //注册自定义的Native模块
            modules.add(new MyNativeBridgeModule(reactContext)); 
            return modules;
        }
    
        @Override
        public List<Class<? extends JavaScriptModule>> createJSModules() {
            return Collections.emptyList(); //return null编译时会出错,要改写成返回空集合
        }
    }
    
    • 在工程Application中,加入自定义的ReactPackage
      ~/MainApplication.java
            @Override
            protected List<ReactPackage> getPackages() {
                //返回带有官方已有的package的集合
                return Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        new MyReactPackage()  //加入自定义的Package类
                );
            }
    
    • Android侧的RNActivity类,继承了ReactActivity
      ~/FirstReactActivity.java
    public class FirstReactActivity extends ReactActivity {
    
        @Override
        protected String getMainComponentName() {
            return "FirstReactComponent";  //注册的react组件名,一会在JS里要用到
        }
    
        //如果回调时不需要回到RN端处理,
        //也可此处定义onActivityResult
        //而不是在MyNativeBridgeModule中写监听
    //    @Override
    //    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    //        super.onActivityResult(requestCode, resultCode, data);
    //        switch (requestCode){
    //            case 1002:
    //                Toast.makeText(this,data.getStringExtra("intentData"),Toast.LENGTH_SHORT).show();
    //                break;
    //        }
    //    }
    }
    
    • RN侧的示例代码
      ~/FirstReactComponent.js
    export default class FirstReactComponent extends Component {
      constructor(props) {
        super(props);
        this.state = {
          title:'大家好,我是React界面',
          intentData:'',
        };
      }
    
      //调用原生方法 showToast
      _showToast = ()=>{
        NativeModules.MyNativeBridgeModule.showToast('调用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
      }
    
      //调用原生方法 并获取回调结果
      _testCallback = ()=>{
        NativeModules.MyNativeBridgeModule.testCallBack(this.state.title,
          (result)=>{
            console.log(result);
            //获取了回调结果,并修改了state的title
            this.setState({
              title:result,
            })
          },
          (error)=>{
            console.log(error);
          }
        );
      }
    
      //代码层接管RN的物理返回键,
      //return true不做RN层的返回处理
      //交由Native层处理ActivityResult
      _onBackAndroid = () => {
        NativeModules.MyNativeBridgeModule.finishActivityForResult("回传onActivityResult值1");
        return true;
      }
    
      componentDidMount() {
        //调用原生方法,获取Activity的Intent数据
        NativeModules.MyNativeBridgeModule.getDataFromIntent(
          (result) => {
            //获取了回调结果,并修改了state的title
            this.setState({
              intentData:result,
            })
          },
          (error) => {
            console.log(error);
          }
        );
    
        //注册Android物理返回键监听
        BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);
    
         //注册通知
        this.subscription = DeviceEventEmitter.addListener('notify',(result)=>{
          NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
        });
      }
    
      componentWillUnmount() {
        //解绑Android物理返回键监听
        BackHandler.removeEventListener('hardwareBackPress', this._onBackAndroid);
        // 移除通知
        this.subscription.remove();
      }
    
      //调用原生方法,打开新的Activity,并可传递数据
      _startNewActivity = ()=>{
        NativeModules.MyNativeBridgeModule.startNewActivityByString("","",(result)=>{
          NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
        });
      }
    
      render() {
        //获取原生常量值
        const Native_Constants_A = NativeModules.MyNativeBridgeModule.Native_Constants_A;
        return (
          <View style={styles.container}>
            <Text style={styles.welcome}>
              {this.state.title}
            </Text>
            <Text style={styles.instructions}>
              {this.state.intentData}
            </Text>
            <Text style={styles.instructions}>
              {Native_Constants_A}
            </Text>
            <TouchableOpacity onPress={this._showToast} style={styles.button}>
              <Text style={styles.instructions}>
                点我调用原生Toast
              </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._testCallback} style={styles.button}>
              <Text style={styles.instructions}>
                点我调用原生方法并获取回调结果
              </Text>
            </TouchableOpacity>
            <TouchableOpacity onPress={this._startNewActivity} style={styles.button}>
              <Text style={styles.instructions}>
                点我打开原生Activity(RN->Native)
              </Text>
            </TouchableOpacity>
          </View>
        );
      }
    }
    //暴露给原生使用
    AppRegistry.registerComponent('FirstReactComponent', () => FirstReactComponent);
    

    3)访问原生侧常量

    在自定义的原生模块中,通过重写getConstants()即可被RN访问常量。
    RN通过NativeModules.MyNativeBridgeModule.Native_Constants_A;即可调用。
    ~/MyNativeBridgeModule.java

        //此方法可被RN端访问常量
        @Nullable
        @Override
        public Map<String, Object> getConstants() {
            final Map<String, Object> constants = new HashMap<String, Object>();
            constants.put("Duration_Short", Toast.LENGTH_SHORT);
            constants.put("Duration_Long", Toast.LENGTH_LONG);
            constants.put("Native_Constants_A", "我是Native常量值");
            return constants;
        }
    

    ~/FirstReactComponent.js

    NativeModules.MyNativeBridgeModule.Native_Constants_A;
    

    4)访问原生侧方法

    原生通过注解 @ReactMethod暴露

    4.1)void无返回

        //@ReactMethod 此注解定义与RN端的调用方法
        @ReactMethod
        public void showToast(String msg, int duration) {
            Toast.makeText(getReactApplicationContext(), msg, duration).show();
        }
    
      //调用原生方法 showToast
      _showToast = ()=>{
        NativeModules.MyNativeBridgeModule.showToast('调用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
      }
    

    4.2)有返回回调

    由于跨端的访问都是异步进行,可以通过Callback回调函数获取返回值

        //方法的返回类型必须为void,跨端访问为异步进行,需要返回值须写回调
        @ReactMethod
        public void testCallBack(String msg, Callback successCB, Callback errorCB) {
            try {
                String result = msg + " ,但我被testCallBack方法修改了";
                successCB.invoke(result);
            } catch (Exception e) {
                errorCB.invoke("异常:" + e.getMessage());
            }
        }
    
      //调用原生方法 并获取回调结果
      _testCallback = ()=>{
        NativeModules.MyNativeBridgeModule.testCallBack(this.state.title,
          (result)=>{
            console.log(result);
            //获取了回调结果,并修改了state的title
            this.setState({
              title:result,
            })
          },
          (error)=>{
            console.log(error);
          }
        );
      }
    

    5)原生启动RN

    Intent intent = new Intent(this,FirstReactActivity.class);
    intent.putExtra("intentData","我是MainActivity传递的intentData");
    startActivityForResult(intent,1001);
    

    5.1)RN获取Activity传递的Intent数据

        //实例:原生->RN 获取之前Activity传递的数据
        @ReactMethod
        public void getDataFromIntent(Callback successCB, Callback errorCB) {
            try {
                Activity currentActivity = getCurrentActivity();
                String intentString = currentActivity.getIntent().getStringExtra("intentData");
                successCB.invoke(intentString);
            } catch (Exception e) {
                errorCB.invoke("异常:" + e.getMessage());
            }
        }
    
    componentDidMount() {
        //调用原生方法,获取Activity的Intent数据
        NativeModules.MyNativeBridgeModule.getDataFromIntent(
          (result) => {
            //获取了回调结果,并修改了state的title
            this.setState({
              intentData:result,
            })
          },
          (error) => {
            console.log(error);
          }
        );
    }
    

    5.2)startActivityForResult返回Intent数据给Activity

        //实例:原生->RN  startActivityForResult 返回数据给之前的Activity
        @ReactMethod
        public void finishActivityForResult(String msg) {
            Activity currentActivity = getCurrentActivity();
            Intent intent = new Intent();
            intent.putExtra("intentData", msg);
            currentActivity.setResult(Activity.RESULT_OK, intent);
            currentActivity.finish();
        }
    

    通过接管返回操作来优先调用@ReactMethod方法。若在componentWillUnmount()中处理会导致Activity优先接收到onActivityResult,而后进入@ReactMethod方法。

    //代码层接管RN的物理返回键,
    //return true不做RN层的返回处理
    //交由Native层处理ActivityResult
    _onBackAndroid = () => {
         NativeModules.MyNativeBridgeModule.finishActivityForResult("回传onActivityResult值1");
         return true;
    }
    
    componentDidMount() {
      //注册Android物理返回键监听
      BackHandler.addEventListener('hardwareBackPress', this._onBackAndroid);
    }
    componentWillUnmount() {
      //解绑Android物理返回键监听
      BackHandler.removeEventListener('hardwareBackPress', this._onBackAndroid);
    }
    

    6)RN启动原生

    RN启动原生可采用隐式或显示(须反射)启动

    6.1)Activity获取RN传递的Intent数据

        //实例: RN->原生  打开新的Activity
        //实际项目中可进行实际封装
        @ReactMethod
        public void startNewActivityByString(String activityName, String data, Callback resultCB) {
            Activity currentActivity = getCurrentActivity();
            //此处采用隐式启动,方便封装。若显示启动,需要反射获取class,或业务层上做kv映射。
            Intent intent = new Intent("com.tgf.studyrn_native_android.SecondActivity");
            //此处采用显示启动,需要反射
    //        Class aimActivity = null;
    //        try {
    //            aimActivity = Class.forName("com.tgf.studyrn_native_android.SecondActivity");
    //        } catch (ClassNotFoundException e) {
    //            e.printStackTrace();
    //        }
    //        Intent intent = new Intent(currentActivity,aimActivity);
    
            //将回调函数赋值给全局变量,以便全局callback在mActivityEventListener中使用
            secondActivityOnActivityResultCallback = resultCB;
            currentActivity.startActivityForResult(intent, 1002);
        }
    
      //调用原生方法,打开新的Activity,并可传递数据
      _startNewActivity = ()=>{
        NativeModules.MyNativeBridgeModule.startNewActivityByString("","",(result)=>{
          NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
        });
      }
    

    6.2)startActivityForResult返回Intent数据给RN

    须定义监听BaseActivityEventListener,通过其onActivityResult来获取。
    方式一:全局变量secondActivityOnActivityResultCallback发出回调给RN
    方式二:rnContext.getJSModule发出通知给RN

    //定义全局回调,RN->原生  startActivityForResult 返回数据给之前的 RNActivity
    private Callback secondActivityOnActivityResultCallback;
    
    //定义全局rnContext
    private ReactApplicationContext rnContext;
    
    public MyNativeBridgeModule(ReactApplicationContext reactContext) {
      super(reactContext);
      rnContext = reactContext;
      //定义监听 RN->原生  startActivityForResult 返回数据给之前的 RNActivity
      reactContext.addActivityEventListener(mActivityEventListener);
    }
    
    //实例:RN->原生  startActivityForResult 返回数据给之前的 RNActivity
    //方式一 : Callback回调
    //方式二 : 发送通知
    private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
      @Override
      public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
        switch (requestCode) {
          case 1002:
      //方式一 : Callback回调
          //try {
          //secondActivityOnActivityResultCallback.invoke(intent.getStringExtra("intentData"));
          //}catch (Exception e){
          //}
    
      //方式二 : 发送通知
            rnContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("notify", intent.getStringExtra("intentData"));
            break;
        }
      }
    };
    

    6.3)原生发送通知给RN

    发送部分参见6.2

      componentDidMount() {
         //注册通知
        this.subscription = DeviceEventEmitter.addListener('notify',(result)=>{
          NativeModules.MyNativeBridgeModule.showToast(result,NativeModules.MyNativeBridgeModule.Duration_Short);
        });
      }
    
      componentWillUnmount() {
        // 移除通知
        this.subscription.remove();
      }
    

    7)UI互嵌

    7.1)原生界面内部分使用RN的界面

    原生界面内部分使用RN的界面

    *实例:在原生Activity中部分使用RN的UI,应将Rn的组件作为Android中的fragment来使用

    • 新建MyReactFragment继承Fragment
    public abstract class MyReactFragment extends Fragment {
        private ReactRootView mReactRootView;
        private ReactInstanceManager mReactInstanceManager;
    
        //返回RN 的 Appregistry注册的组件名字.
        public abstract String getMainComponentName();
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            mReactRootView = new ReactRootView(context);
            mReactInstanceManager =
                    ((MainApplication) getActivity().getApplication())
                            .getReactNativeHost()
                            .getReactInstanceManager();
        }
    
        //这里改写根View为ReactRootView,因此继承此类的fragment实现`getMainComponentName`即可
        @Override
        public ReactRootView onCreateView(LayoutInflater inflater, ViewGroup group, Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            return mReactRootView;
        }
    
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            mReactRootView.startReactApplication(
                    mReactInstanceManager,
                    getMainComponentName(),
                    null
            );
        }
    }
    
    • 新建ThirdReactFragment继承第一步创建的MyReactFragment
    public class ThirdReactFragment extends MyReactFragment {
        @Override
        public String getMainComponentName() {
            //对应RN 的 Appregistry注册的组件名字.
            return "ThirdReactComponent";
        }
    }
    
    • RN侧创建ThirdReactComponent组件给原生侧使用
    export default class ThirdReactComponent extends Component {
        //调用原生方法 showToast
        _showToast = ()=>{
            NativeModules.MyNativeBridgeModule.showToast('调用原生Toast',NativeModules.MyNativeBridgeModule.Duration_Short);
        }
    
        render() {
            return (
            <View style={styles.container}>
                <TouchableOpacity onPress={this._showToast}>
                <Text>大家好 我是React的UI,我准备嵌入到原生UI里</Text>
                </TouchableOpacity>
            </View>
            );
        }
    }
    //暴露给原生使用
    AppRegistry.registerComponent('ThirdReactComponent', () => ThirdReactComponent);
    
    • Android创建Activity
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="com.tgf.studyrn_native_android.SecondActivity">
        
        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="100dp"></FrameLayout>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:layout_centerInParent="true"
            android:text="大家好,我是原生SecondActivity"/>
    </LinearLayout>
    
    public class SecondActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    
        private ReactInstanceManager mReactInstanceManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
    
            mReactInstanceManager =
                    ((MainApplication) getApplication()).getReactNativeHost().getReactInstanceManager();
            Fragment viewFragment = new ThirdReactFragment();
            getSupportFragmentManager().beginTransaction().add(R.id.container,viewFragment).commit();
        }
    
        //挂载的Activity还需要实现DefaultHardwareBackBtnHandler接口,以保证RN的生命周期=========
        @Override
        public void invokeDefaultOnBackPressed() {
            super.onBackPressed();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostPause();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            if (mReactInstanceManager != null) {
                mReactInstanceManager.onHostResume(this, this);
            }
        }
    }
    

    7.2)RN界面内部分使用原生的界面

    RN界面内部分使用原生的界面

    *示例:在RN的界面中部分使用原生的TextView组件。

    • 创建一个视图管理类MyTextViewManager
    public class MyTextViewManager extends SimpleViewManager<ReactTextView> {
    
        @Override
        public String getName() {
            //方法返回的名字会用于在JavaScript端引用这个原生视图
            return "MyTextViewManager";
        }
    
        @Override
        protected ReactTextView createViewInstance(ThemedReactContext reactContext) {
            ReactTextView textView = new ReactTextView(reactContext);
            return textView;
        }
    
        //@ReactProp
        //(name = "text")  这个参数指定了对应属性在JavaScript端的名字
        @ReactProp(name = "text")
        public void setText(ReactTextView textView,String text){
            textView.setText(text);
        }
    }
    
    • 在MyReactPackage注册第一步新建的ViewManager
      ~/MyReactPackage.java
    @Override
        public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            List<ViewManager> modules = new ArrayList<>();
            modules.add(new MyTextViewManager()); //注册自定义的ViewManager模块
            return modules;
        }
    
    • 实现对应的JavaScript模块
    import { PropTypes } from 'react';
    import { requireNativeComponent, View } from 'react-native';
    
    var myTextView = {
      name: 'MyTextView',
      propTypes: {
        text:PropTypes.string,
        ...View.propTypes //包含默认的View的属性,如果没有这句会报‘has no propType for native prop’错误
      },
    };
    
    module.exports = requireNativeComponent('MyTextViewManager', myTextView);
    
    • 在Rn组件中引用此JS模块
    import MyTextView from './MyTextView';
    export default class SecondReactComponent extends Component {
      constructor(props) {
        super(props);
        this.state = {
          title:'大家好,我是SecondReactComponent界面',
        };
      }
    
      render() {
        return (
          <View style={styles.container}>
            <MyTextView
                style={styles.welcome}
                text={'大家好,我使用了原生自定义的MyTextView组件'}/>
            <Text>{this.state.title}</Text>
          </View>
        );
      }
    }
    //暴露给原生使用
    AppRegistry.registerComponent('SecondReactComponent', () => SecondReactComponent);
    
    • 新建SecondReactActivity继承ReactActivity
    public class SecondReactActivity extends ReactActivity {
    
        @Override
        protected String getMainComponentName() {
            return "SecondReactComponent";  //注册的react组件名,一会在JS里要用到
        }
    }
    

    参考资料

    官网
    https://github.com/ipk2015/RN-Resource-ipk/tree/master/react-native-docs


    相关文章

      网友评论

          本文标题:ReactNative原生集成-Android

          本文链接:https://www.haomeiwen.com/subject/ihvrwxtx.html