android 混编,ReactNative混合开发-3 Android混编配置

开发语言:ReactNative 0.59.5 Android

开发环境:VSCode Android Studio 3.4

1、项目目录

首先,我们按照建立一下目录结构,其中:

Code目录放置所有公用的ReactNative脚本,包,以及相关配置。

Android目录放置原Android项目。

Code (根目录)

--Android(一级目录)

2、开发环境准备

2.1、package.json配置

在Code目录下创建package.json文件,编辑文件输入以下内容。

{

"name": "AppName",

"version": "0.0.1",

"private": true,

"scripts": {

"start": "yarn react-native start"

}

}

2.2、React和React Native模块安装

在Code目录下使用控制台执行以下语句来安装React Native。

yarn add react-native

注意,执行完以上命令后,可能会出现以下提示内容,表示我们需要安装指定版本的React(此例子中需要安装版本为16.8.3的React)。

warning " > react-native@0.59.5" has unmet peer dependency "react@16.8.3".

在Code目录下使用控制台执行以下语句来安装指定版本的React

yarn add react@16.8.3

3、配置maven

3.1、在app的build.gradle文件中添加React Native依赖

dependencies {

...

implementation "com.facebook.react:react-native:+" // 新增React Native依赖

}

3.2、在项目的build.gradle文件中添加maven的依赖入口

allprojects {

repositories {

...

maven { url "$rootDir/../../node_modules/react-native/android"} //注意url路径应该指向根目录code中的node_modules,

}

}

3.3、在AndroidManifest.xml声明网络权限

package="com.example.reactnativedemo" >

//新增网络权限

...

3.4、在AndroidManifest.xml配置调试Activity

package="com.example.reactnativedemo" >

...

//调试Activiy,使用摇一摇呼出

4、脚本创建

在Code根目录下创建Scripts文件夹,用于存放React Native的脚本文件

Code (根目录)

--Scripts(一级目录,用于存放所有React Native的脚本)

然后我们可以在Scripts目录下开始写ReactNative的脚本了。

首先我们创建一个FrameText.js,然后写入如下内容:

import React, { Component } from 'react'

import { View, Text } from 'react-native'

export default class FrameText extends Component {

render() {

return (

width:200,

height:100,

backgroundColor: '#CDDAF5'

}}>

{"我来自ReactNative,我是FrameText"}

);

}

}

// 整体js模块的名称

export { FrameText }

在FrameText中,我们创建了一个简单的组件,供其他脚本使用。

然后我们再创建一个index.js,然后写入如下内容

import {AppRegistry} from 'react-native'

import {FrameText} from 'FrameText'

// 整体js模块的名称

AppRegistry.registerComponent('Component-1', () => FrameText);

在index中,我们注册了FrameText组件,供app使用,我们可以在index.js注册很多不同的组件,app可以通过我们注册的名字(本例中为Component-1)来创建这些组件,下面我们来看看怎么在app内使用他们。

5、Android项目修改

本例中期望在app的一个controller内,同时使用原生语言与ReactNative脚本分别显示2个View,现在我们来看看是如果在原生app中加载ReactNative的View。

e1ac474a9bb1

5.1、创建 MyReactNativeBridge

新建一个Java文件,创建MyReactNativeBridge类,顾名思义,此类负责桥接原生app与ReactNative,注意,一个app中最好只创建一个桥接实例,所以使用单利模式创建。

package com.example.reactnativedemo;

import com.facebook.react.ReactInstanceManager;

import com.facebook.react.common.LifecycleState;

import com.facebook.react.shell.MainReactPackage;

public class MyReactNativeBridge {

private static final ReactInstanceManager mReactInstanceManager = ReactInstanceManager.builder()

.setApplication(MyApplication.getInstance())

.setBundleAssetName("index.android.bundle")

.setJSMainModulePath("Scripts/index")

.addPackage(new MainReactPackage())

.setUseDeveloperSupport(BuildConfig.DEBUG)

.setInitialLifecycleState(LifecycleState.RESUMED)

//注册弹出调试菜单的Activity,发布版可以无需注册

.setCurrentActivity(MyApplication.getInstance().getCurrentActivity())

.build();

private MyReactNativeBridge() {

}

public static ReactInstanceManager getInstance() {

return mReactInstanceManager;

}

}

5.2、创建并使用ReactRootView

ReactRootView为ReactNative脚本描述的View,它继承FrameLayout,我们可以通过MyReactNativeBridge来创建ReactRootView。

public class MainActivity extends AppCompatActivity {

private ReactRootView mReactRootView;

LinearLayout reactView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

reactView = findViewById(R.id.reactLayout);

MyApplication.getInstance().setCurrentActivity(this);

mReactRootView = new ReactRootView(this.getApplicationContext());

mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", null);

reactView.addView(mReactRootView);

}

}

现在我们在真机上运行模拟器,并且命令开启ReactNative服务器(yarn start),就可以看到上面例子中的画面了。

6、原生与ReactNative通信

6.1、原生向ReactNative传递数据

注意我们在startReactApplication时的语句的第三个参数initialProperties,代表由原生向ReactNative传递的参数。

mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", null);

现在修改创建语句和脚本

Java代码:通过initialProperties向JS传递参数

public class MainActivity extends AppCompatActivity {

private Bundle mockData = new Bundle();

protected void onCreate(Bundle savedInstanceState) {

...

mockData.putString("content", "初始化");

mReactRootView = new ReactRootView(this.getApplicationContext());

mReactRootView.startReactApplication(MyReactNativeBridge.getInstance(), "Component-1", mockData);

reactView.addView(mReactRootView);

}

}

JS脚本:通过this.props["content"]使用原生App传递的参数(也可以使用this.props.content)

...

export default class FrameText extends Component {

render() {

return (

width:200,

height:100,

backgroundColor: '#CDDAF5'

}}>

{this.props["content"]}

);

}

}

...

重新编译代码后,再次运行App,可以看到界面变成如下的样子

e1ac474a9bb1

ReactRootView还有一个方法setAppProperties,我们可以通过这个方法来对已经创建的View传递参数。

Java代码:通过setAppProperties属性向已创建的View传递参数

protected void onCreate(Bundle savedInstanceState) {

...

mockData.putString("content", "重加载");

mReactRootView.setAppProperties(mockData);

...

}

重新编译代码后,再次运行App,可以看到界面变成如下的样子

e1ac474a9bb1

6.2、ReactNative向原生传递数据

我们使用ReactContextBaseJavaModule来定义一个ReactNative中的NativeModules类型。在ReactContextBaseJavaModule中,我们可以使用@ReactMethod注解来提供结构供脚本回调。

首先我们创建一个MyReactNativeBridge.swift文件

package com.example.reactnativedemo;

import com.facebook.react.bridge.ReactApplicationContext;

import com.facebook.react.bridge.ReactContextBaseJavaModule;

import com.facebook.react.bridge.ReactMethod;

public class MyReactNativeCommunication extends ReactContextBaseJavaModule {

public MyReactNativeCommunication(ReactApplicationContext reactContext) {

super(reactContext);

}

//提供Test方法

@ReactMethod

public void test(String str) {

System.out.println(str);

}

//提供在NativeModules中该类的名字

@Override

public String getName() {

return "MyReactNativeCommunication";

}

}

然后我们使用MyReactNativePackage来注册这个类,否则脚本无法使用

package com.example.reactnativedemo;

import com.facebook.react.ReactPackage;

import com.facebook.react.bridge.NativeModule;

import com.facebook.react.bridge.ReactApplicationContext;

import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;

import java.util.Collections;

import java.util.List;

public class MyReactNativePackage implements ReactPackage {

@Override

public List createViewManagers(ReactApplicationContext reactContext) {

return Collections.emptyList();

}

@Override

public List createNativeModules(

ReactApplicationContext reactContext) {

List modules = new ArrayList<>();

modules.add(new MyReactNativeCommunication(reactContext));

return modules;

}

}

然后在MyReactNativeBridge将MyReactNativePackage添加到mReactInstanceManager中

public class MyReactNativeBridge {

private static final ReactInstanceManager mReactInstanceManager = ReactInstanceManager.builder()

.setApplication(MyApplication.getInstance())

.setBundleAssetName("index.android.bundle")

.setJSMainModulePath("Scripts/index")

.addPackage(new MainReactPackage())

.addPackage(new MyReactNativePackage())//新增MyReactNativePackage

.setUseDeveloperSupport(BuildConfig.DEBUG)

.setInitialLifecycleState(LifecycleState.RESUMED)

.setCurrentActivity(MyApplication.getInstance().getCurrentActivity())

.build();

}

最后修改JS代码,调用test方法

import { NativeModules } from 'react-native'

export default class FrameText extends Component {

render() {

NativeModules.MyReactNativeCommunication.test("我回来啦");

...

}

}

重新编译代码后,再次运行App,可以看到Android的输出 “我回来啦”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值