我尽量用词准确,不打错别字,不造成阅读障碍。
最近项目要使用RN,虽然去年就学过了,但是学的不系统,也没在原生中使用过,借此机会,回顾一下文档。这篇文章是记录原生中嵌入RN的界面,分两种,一.单独的Activity使用RN,二.原生页面加入RN页面,两个页面混合。这是一篇适合初学者的文章,将官网上的方法自己实践了一遍并指出了可能会遇到一些坑。
先附上中文网链接,有些问题请看上面的解释:
https://reactnative.cn/docs/0.51/integration-with-existing-apps.html#content
一.单独的Activity引入RN页面
1.project中项目根目录下创建文件: package.json文件并添加如下代码:
{
"name": "HelloRN", //项目名
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.0.0-alpha.12",
"react-native": "0.47.2"
},
"devDependencies": {
"babel-jest": "20.0.3",
"babel-preset-react-native": "3.0.1",
"jest": "20.0.4",
"react-test-renderer": "16.0.0-alpha.12"
},
"jest": {
"preset": "react-native"
}
}
没什么注意的,看着注释来就好,网上有使用“npm init”,然后各种设置的,我试了,没成功,不知道为什么失败了,也不想去探究了,明明有正确简单的方法,中文网上的翻译显示官方也推荐使用简单方法。
2.project中项目根目录下添加index.android.js文件,代码如下:
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
class HelloWorldApp extends Component {
render() {
return ( <Text>Hello world!</Text> );
}
}
// 注意,HelloWorldAPP必须与类名一致
AppRegistry.registerComponent('HelloWorld', () => HelloWorldApp);
这里的HelloWorldApp必须与类名一致,单引号里面的HelloWorld是后面要使用到的。
最后结果如下:
3.在AS的Terminal(自带命令行工具)中输入npm install
成功后在项目下会有一个node_modules的文件夹出现,请看上图。
4.项目添加依赖
在项目的build.gradle中(不是app的gradel)的allprojects中的repositories下添加:
maven{
url "$rootDir/node_modules/react-native/android"
}
注:添加完后,AS会提醒你“Sync Now”,我在点击后出了问题,没找到解决方法,为此,我直接在模拟器上运行了程序,可以成功运行,此时问题自己就消失了。
5.module添加依赖
在app的gradle中添加依赖,就是平常添加依赖的地方;
compile "com.facebook.react:react-native:+"
//AS3.0以后改为 implementation “com.facebook.react:react-native:+”也可。
注:与上面一样,”Sync now”后就有问题,可能是我特有的问题,还是运行一下程序就好了。
6.在应用的Application中实现ReactApplication,如果不能导入ReactApplication,则说明前面的步骤出了问题。
代码如下:
package com.clone.surpassli.rndemo;
import android.app.Application;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;
import java.util.Arrays;
import java.util.List;
/**
* Created by SurpassLi.
*/
public class MyApplicatioin 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);
}
}
注:记得在Manifest文件中配置:
<application
android:name=".MyApplicatioin"
...
>
....
</application>
7.新建Activity继承ReactActivity,中文网上和网上的实现DefaultHardwareBackBtnHandler接口也可以
代码如下:
package com.clone.surpassli.rndemo;
import com.facebook.react.ReactActivity;
public class RNActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "HelloWorld"; //此处的HelloWorld与‘index.android.js’中引号内的HelloWorld一致
}
}
注:别忘了注册Activity; 注意此处的返回值与index.android.js一致,顾名思义就是去找这个控件。
8.在MainActivity中写跳转代码
增加一个Button并添加点击事件跳转到RNActivity中:
9.启动服务
进入项目目录下,启动命令行工具,使用react-native start启动服务,确保其他服务未启动,端口未占用,可根据报错信息更改。
大功告成,效果如下:
这是跳转过后的页面,主意这个页面没有ToolBar也没有ActionBar,你要自己写,如果想有ToolBar或ActionBar就需要用下面的方法,但是ToolBar功能复杂的话还要考虑交互。
二.原生页面和RN页面混合
其他的步骤和上面一样,但是不用写Application和部署,因为在下面写了,就和中文网一样,但是中文网的方法我没试,我是在写了Application的前提下写的。
1.在布局文件中添加控件:
<com.facebook.react.ReactRootView
android:id="@+id/rnview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
2.在Activity下添加:
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
.......
mReactRootView = (ReactRootView) findViewById(R.id.rnview);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
//.setUseOldBridge(true) // uncomment this line if your app crashes
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "HelloWorld", null);//这个HelloWorld与上面一样,要对应
最终效果:
没错,如果上面没有Button,那么就相当于RN的View充斥着整个屏幕了,此时是有ToolBar的。你可能想过在RNActivity中添加OnCreate方法并setContentView加载布局,实际情况是,会覆盖掉你的RN布局,只显示你加载的布局。
如有错误,欢迎指正;
参考(感谢):
https://www.jianshu.com/p/ee72b94ae8b1
https://blog.youkuaiyun.com/liu__520/article/details/52817016