zoukankan      html  css  js  c++  java
  • 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声明网络权限

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.reactnativedemo" >
        
        
        <uses-permission android:name="android.permission.INTERNET" /> //新增网络权限
         ...
    </manifest>
    

    3.4、在AndroidManifest.xml配置调试Activity

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.reactnativedemo" >
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application
        
            ...
            //调试Activiy,使用摇一摇呼出
            <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
            
     
     
         </application>
    
    </manifest>
    

    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 (
                <View style={{
                    width:200,
                    height:100,
                    backgroundColor: '#CDDAF5'
                }}>
                <Text>{"我来自ReactNative,我是FrameText"}</Text>
                </View>
            );
        }
    }
    // 整体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。

     
     

    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 (
                <View style={{
                    width:200,
                    height:100,
                    backgroundColor: '#CDDAF5'
                }}>
                <Text>{this.props["content"]}</Text>
                </View>
            );
        }
    }
    
    ...
    

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

     
     

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

    • Java代码:通过setAppProperties属性向已创建的View传递参数
    protected void onCreate(Bundle savedInstanceState) {
        ...
        
        mockData.putString("content", "重加载");
        mReactRootView.setAppProperties(mockData);
        
        ...
    }
        
    

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

     
     

    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<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
            return Collections.emptyList();
        }
    
    
        @Override
        public List<NativeModule> createNativeModules(
                ReactApplicationContext reactContext) {
            List<NativeModule> 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的输出 “我回来啦”



    作者:肆点壹陆
    链接:https://www.jianshu.com/p/e1ac474a9bb1
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    SharePoint 2013 安装.NET Framework 3.5 报错
    SharePoint 2016 配置工作流环境
    SharePoint 2016 站点注册工作流服务报错
    Work Management Service application in SharePoint 2016
    SharePoint 2016 安装 Cumulative Update for Service Bus 1.0 (KB2799752)报错
    SharePoint 2016 工作流报错“没有适用于此应用程序的地址”
    SharePoint 2016 工作流报错“未安装应用程序管理共享服务代理”
    SharePoint JavaScript API in application pages
    SharePoint 2016 每天预热脚本介绍
    SharePoint 无法删除搜索服务应用程序
  • 原文地址:https://www.cnblogs.com/qing123/p/13045090.html
Copyright © 2011-2022 走看看