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

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

1,安装React Native

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

npm init

操作完成之后,在你的Android项目根目录下会出现一个package.json文件。
这里写图片描述
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" 
}

这里借用网络的一张图,我原生的项目的依赖比较多。
这里写图片描述

然后在项目的根目录下的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中的配置比较多,所以我将上的配置部分单独抽取出来,也就是下面的方式。
这里写图片描述

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页面即可。如图:
这里写图片描述

5,启动云运行

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

npm start

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

这里写图片描述

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

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

附:Android原生集成RN源码

发布评论
IT虾米网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

React Native悬浮效果组件详解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。