欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android原生项目集成React Native

程序员文章站 2022-07-02 22:08:23
...

最近,很多的公司,特别是小公司、小项目,为了解决人力成本的问题,都开发将移动原生开发转到了跨平台开发,或者原生+h5的混合开发,今天要说的是如何在原生项目中集成React Native。

如果是一个新项目,并且以应用为主的,大可以使用React Native来进行开发,关于这方面的内容,不做讲解,读者可以查看我之前的博客,或者阅读《React Native移动开发实战》。

1,安装React Native

首先,在你的安卓项目的根目录下执行如下命令:

npm init

操作完成之后,在你的Android项目根目录下会出现一个package.json文件。
Android原生项目集成React Native
package.json主要是项目的RN的依赖配置文件,其内容如下:

{
  "name": "kingtv",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.4.0",
    "react-native": "^0.51.1"
  }
}

从配置信息可以看出,react安装的是16.4.0,react-native安装的是0.51.1。然后执行命令:

 npm install

此时,你会发现Android项目根目录下多了一个node_modules文件夹。
然后使用如下命令安装React和React Native

npm install -save react
npm install -save react-native

2,依赖添加

配置Android项目react-native依赖库:

compile"com.facebook.react:react-native:+"//(+号代表使用最新版本)

然后,添加NDK支持。

ndk {
   abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
}

这里借用网络的一张图,我原生的项目的依赖比较多。
Android原生项目集成React Native

然后在项目的根目录下的build.gradle中添加maven配置。

maven {
      url "$rootDir/node_modules/react-native/android"
    }

如果上面配置的时候报如下错误:

Error:Conflict with dependency 'com.google.code.findbugs:jsr305' in project ':app'. Resolved versions for app (3.0.0) and test app (2.0.1) differ. See http://g.co/androidstudio/app-test-app-conflict for details.

请将下面的配置添加到app的build.gradle,配置的脚本信息如下:

android {
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
    }
}

到此,React Native的相关环境就配置完成了,接下来就可以编写代码了,下面我们以一个原生的页面跳转到React Native页面为例。

3, 实例

1、Application修改

想要项目中使用React Native,需要重写ReactNativeHost,一般的写法是直接在Application中做如下的添加。

public class RNApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
        //注意:BuildConfig需要导入自己项目包名下的BuildConfig
        return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
                new MainReactPackage()
        );
    }
};

@Override
public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
}

@Override
public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
}
}

但是,由于我的项目的Application中的配置比较多,所以我将上的配置部分单独抽取出来,也就是下面的方式。
Android原生项目集成React Native

2,创建index.android.js文件

然后我们在项目的根目录下创建index.android.js文件,文件的内容如下:

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, 我是React Native</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('ReactHost', () => HelloWorld);

3,绑定原生界面

方法一

想要通过原生代码调用 React Native页面 ,我们需要在一个 Activity 中创建一个 ReactRootView 对象,将它关联一个 React application ,并将该界面设置为主视图。例如,ReactActivity的源码如下:

public class ReactHostActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        // 注意这里的react-example必须对应“index.android.js”中的
        // “AppRegistry.registerComponent()”的第一个参数
        mReactRootView.startReactApplication(mReactInstanceManager, "ReactHost", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @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();
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}

方法二

当然也可以使用继承自ReactActivity,然后重写getMainComponentName()即可。

public class ReactHostActivity extends ReactActivity  {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "ReactHost";
    }
}

注意这里的返回组件的名称和index.js文件中名称的对于关系。例如:

AppRegistry.registerComponent('ReactHost', () => ReactHost);

由于ReactActivity 的许多组件都使用了 Theme.AppCompat.Light.NoActionBar这一主题 ,所以需要将ReactHostActivity的主题设置为Theme.AppCompat.Light.NoActionBar。

<activity 
      android:name=".ReactHostActivity"
      android:label="@string/app_name"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        </activity>

4,配置权限

如果你的项目还没有添加如下权限,需要先添加如下的权限。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

为了简单,我们给原生项目的设置页面绑定一个跳转事件,使用Intent方式先跳转到ReactHostActivity页面即可。如图:
Android原生项目集成React Native

5,启动云运行

要想运行混合的项目,需要先启动开发服务器(Packager),也就是启动React Native相关的环境,启动的命令如下:

npm start

然后在Android Studio中启动Android原生项目,不出意外的话,当你点击项目的设置按钮的时候,将会看到js的加载渲染,不错这就是React Native在在加载js。
Android原生项目集成React Native

Android原生项目集成React Native

到此,简单集成就ok了,然后就可以使用React Native愉快的开发了,下面给大家提供一个完整的RN学习项目:React Native美团项目

同时,如果大家在集成过程中遇到什么问题,欢迎大家留意,我会第一时间回复。

附:Android原生集成RN源码