前言

当初不少利用都是采纳了混合开发模式,不论是原生加RN,或是原生加Flutter,或是原生加H5。原生实现主业务线,其余局部能够借助跨平台计划开发,进步开发效率,或者实现热更新,调高业务迭代效率。

上面简略介绍一下Android原生集成最新RN版本的过程。

增加package.json文件

首先在一个失常编译运行的原生APP根目录下执行yarn init命令,按提醒填写根本信息后会在我的项目根目录下,创立一个package.json文件。

增加JavaScript依赖,生成node_modules

而后,应用如下命令增加React和React Native运行环境的反对脚本。

yarn add react react-native

命令执行实现后,所有JavaScript依赖模块都会被装置到我的项目根目录下的node_modules/目录中。

留神:node_modules这个目录咱们原则上不复制、不挪动、不批改、不上传,随用随装,同时把node_modules/目录记录到.gitignore文件中(即不上传到版本控制系统,只保留在本地)。

接下来,在package.json文件中配置启动RN Metro服务的脚本,即script脚本,文件全部内容如下。
我的项目根目录package.json文件

{  "name": "AndroidDemo",  "version": "1.0.0",  "main": "index.js",  "license": "MIT",  "dependencies": {    "react": "^18.2.0",    "react-native": "^0.70.6"  },  "scripts": {    "start": "yarn react-native start"  }}

原生端增加React Native依赖

在app中build.gradle文件中增加React Native和JSC引擎依赖:

dependencies {    ...    implementation "com.facebook.react:react-native:+"    implementation "org.webkit:android-jsc:+"}

在我的项目的build.gradle文件中为React Native和JSC引擎增加maven源的门路,必须写在 "allprojects" 代码块中。

allprojects {    repositories {        maven {            // All of React Native (JS, Android binaries) is installed from npm            url "$rootDir/../node_modules/react-native/android"        }        maven {            // Android JSC is installed from npm            url("$rootDir/../node_modules/jsc-android/dist")        }    }}

!!!留神这里有个问题,点击同步后,会报如下谬误:

Build was configured to prefer settings repositories over project repositories but repository 'maven' was added by build file 'build.gradle'

起因是gradle7.0后,以前位于根我的项目build.gradle文件中的代码库设置当初迁徙到了settings.gradle文件中,根目录build.gradle文件不做更改。
settings.gradle文件配置

dependencyResolutionManagement {    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)    repositories {        google()        mavenCentral()        maven {            url "$rootDir/node_modules/react-native/android"        }        maven {            url("$rootDir/node_modules/jsc-android/dist")        }    }}
相干阐明:https://developer.android.com...

配置原生我的项目网络权限及开发者菜单页面

在原生AndroidManifest.xml文件进行增加,对应示例如下
如果须要拜访http申请,须要application中增加usesCleartextTraffic

// 网络权限 <uses-permission android:name="android.permission.INTERNET" />    <application        android:allowBackup="true"        android:dataExtractionRules="@xml/data_extraction_rules"        android:fullBackupContent="@xml/backup_rules"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:roundIcon="@mipmap/ic_launcher_round"        android:supportsRtl="true"        android:usesCleartextTraffic="true" // 拜访http申请        android:theme="@style/Theme.AndroidStudy"        tools:targetApi="31">        <activity            android:name=".MainActivity"            android:exported="true"><!--            <intent-filter>--><!--                <action android:name="android.intent.action.MAIN" />--><!--                <category android:name="android.intent.category.LAUNCHER" />--><!--            </intent-filter>-->        </activity>        <activity            android:name=".MyActivity"            android:theme="@style/Theme.AppCompat.Light.NoActionBar"            android:exported="true" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        //开发者调试菜单        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />    </application>

创立一个RN入口文件index.js

index.js是 React Native 利用在 Android 上的入口文件。而且它是不可或缺的!它能够是个很简略的文件,简略到能够只蕴含一行require/import导入语句,示例代码如下。

import React from 'react';import {  AppRegistry,  StyleSheet,  Text,  View} from 'react-native';class HelloWorld extends React.Component {  render() {    return (      <View style={styles.container}>        <Text style={styles.hello}>Hello, World</Text>      </View>    );  }}var styles = StyleSheet.create({  container: {    flex: 1,    justifyContent: 'center',    backgroundColor: '#f9c2ff',  },  hello: {    fontSize: 20,    textAlign: 'center',    margin: 10,    color: 'red'  }});AppRegistry.registerComponent(  'MyReactNativeApp',  () => HelloWorld);

创立一个页面用来承载RN页面

须要在一个Activity中创立一个ReactRootView对象,而后在这个对象之中启动React Native利用,并将它设为界面的主视图,这里创立了一个MyActivity页面

import android.app.Activity;import android.os.Bundle;import android.view.KeyEvent;import com.facebook.react.ReactInstanceManager;import com.facebook.react.ReactRootView;import com.facebook.react.common.LifecycleState;import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;public class MyActivity extends Activity implements DefaultHardwareBackBtnHandler {    private ReactRootView mReactRootView;    private ReactInstanceManager mReactInstanceManager;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        SoLoader.init(this, false);        mReactRootView = new ReactRootView(this);        mReactInstanceManager = ReactInstanceManager.builder()                .setApplication(getApplication())                .setCurrentActivity(this)                .setBundleAssetName("index.android.bundle")                .setJSMainModulePath("index")                .addPackage(new MainReactPackage())                .setUseDeveloperSupport(BuildConfig.DEBUG)                .setInitialLifecycleState(LifecycleState.RESUMED)                .build();                // 留神这里的MyReactNativeApp 必须对应"index.js"中的        // "AppRegistry.registerComponent()"的第一个参数        mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);        setContentView(mReactRootView);    }    @Override    protected void onPause() {        super.onPause();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostPause(this);        }    }    @Override    protected void onResume() {        super.onResume();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostResume(this, this);        }    }    @Override    protected void onDestroy() {        super.onDestroy();        if (mReactInstanceManager != null) {            mReactInstanceManager.onHostDestroy(this);        }        if (mReactRootView != null) {            mReactRootView.unmountReactApplication();        }    }// 显示开发调试菜单弹框    @Override    public boolean onKeyUp(int keyCode, KeyEvent event) {        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {            mReactInstanceManager.showDevOptionsDialog();            return true;        }        return super.onKeyUp(keyCode, event);    }    @Override    public void invokeDefaultOnBackPressed() {        super.onBackPressed();    }// 后退按钮事件传递给 React Native    @Override    public void onBackPressed() {        if (mReactInstanceManager != null) {            mReactInstanceManager.onBackPressed();        } else {            super.onBackPressed();        }    }}

自此原生端集成RN实现。

测试集成成果。

首先,须要启动开发服务器(Metro)。你只需在我的项目根目录中执行以下命令:

yarn start

而后,点击Android Studio运行按钮,失常运行我的项目即可。

加载完bundle文件之后,能够看到如下页面了。