• Android端ReactNative环境搭建——下


    接着上文,原生模块sync之后如果没有报错信息,那么我们就可以进入下一步了。我们还是分两大部门来介绍;rn端和原生端。

    • rn端环境搭建(进阶)
      大家还记得上面这篇博客的这幅图吧。这就是我们执行下面命令,生成的原始目录结构。

    npx react-native init AwesomeProject

    在这里插入图片描述
    现在,我们来对它添加一些文件,以完善rn端执行js/ts代码所需要的功能。
    我们需要添加两个文件babel.config.js和metro.config.js。首先,babel.config.js是babel转换器的相关配置,因为es2015使用了一些高级语法,babel则是将这些高级语法转换成浏览器引擎能够识别的语法;metro.config.js则是metro打包相关的配置信息。笔者对这些配置信息也没有深入的了解太多,如果只限于搭建rn环境这个需求,大家如下配置即可。
    在这里插入图片描述

    //在babel.config.js文件中copy下面这段代码
    module.exports = {
        presets: ['module:metro-react-native-babel-preset']
    };
    
    • 1
    • 2
    • 3
    • 4
    //在metro.config.js文件中copy下面这段代码
    module.exports = {
      transformer: {
        getTransformOptions: async () => ({
          transform: {
            experimentalImportSupport: false,
            inlineRequires: false,
          },
        }),
      },
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    细心的同学一定发现了上图中有一个tsconfig.json文件。这个文件是配置相关ts的信息的。因为rn端的代码执行的是js代码,而js代码是动态语言,它最令人恶心的一点是:它是不会报错的。因此,如果用来开发大型项目分分钟搞死开发者,笔者使用的是ts来代替js。因此,需要添加tsconfig.json文件。

    //tsconfig.json
    {
      "compilerOptions": {
        "allowJs": true,
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "isolatedModules": true,
        "jsx": "react-native",
        "module": "commonjs",
        "lib": ["es6"],
        "moduleResolution": "node",
        "noEmit": true,
        "strict": true,
        "target": "esnext",
        "baseUrl": ".",
        "paths": {
        "*": ["src/*"],
        "tests": ["tests/*"],
        "@components/*": ["src/components/*"],
        }
    },
      "exclude": [
        "node_modules",
        "babel.config.js",
        "metro.config.js",
        "jest.config.js"
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    具体细节,感兴趣的同学可以查阅相关的资料,我们这里就不介绍了。
    接着,我们还需要更改的一个文件就是package.json,我们之前刚初始化成功时生成的内容如下所示:

    {
      "name": "AwesomeProject",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node node_modules/react-native/local-cli/cli.js start"
      },
      "dependencies": {
        "react-native": "0.70.3"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    更改后:

    {
      "name": "AwesomeProject",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "yarn react-native start",
        "android": "npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/main.bundle --assets-dest android/app/src/main/res/"
      },
      //我们这里改下react和react-native的版本,因为0.70.3版本使用的是新架构,笔者暂时还不熟悉,所以我们用旧架构来讲解,记住,react和react-native都需要
      "dependencies": {
        "react": "16.9.0",
        "react-native": "^0.63.4",
      },
      //devDependencies里面的内容,大家copy即可,有些依赖例如jest,项目中没有用到的可以移除,当然你添加进去不用它也没有问题
      "devDependencies": {
        "@types/jest": "^27.0.1",
        "@types/react": "^17.0.21",
        "@types/react-native": "^0.65.0",
        "@types/react-test-renderer": "^17.0.1",
        "babel-plugin-module-resolver": "^4.1.0",
        "typescript": "^4.4.3",
        "webpack": "^5.53.0",
        "webpack-cli": "^4.8.0"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    dependencies和devDependencies这两个东西到底是做什么的呢?其实这里的东西就有点像是Android原生gradle中的dependencies闭包,如果我们在原生中想要引入某个依赖一般会如下添加:

     implementation 'com.google.android.material:material:1.4.0'
    
    • 1

    当我们在命令行终端执行yarn命令时,node就会下载dependencies和devDependencies所指定的依赖到node_modules文件夹下面。
    这里有一个小提醒:每次我们进行开发时,最好删掉我们本地的node_modules文件夹,然后重新yarn一下,以确保我们本地的依赖与dependencies和devDependencies块所指定的依赖时一致的。
    官网上是使用npm来下载依赖的,个人不建议使用npm,主要原因就是太慢了,所以大家尽量使用yarn吧!而且有趣的一点是,我们使用npx命令初始化一个rn项目的时候,其实也是用yarn来下载相关的依赖的,因为初始化的工程有一个yarn.lock文件,这就是最好的见证。
    我们改动最大的就是scripts块里面的东西

    "scripts": {
        "start": "yarn react-native start",
        
        "android": "npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/main.bundle --assets-dest android/app/src/main/res/"
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. start是我们调试代码用到的。后面会讲解如何使用这个功能。
    2. android则是打包bundle的命令,上例中我们指定了生成的bundle的名字为main.bundle,将生成的bundle放置在assets目录下,将rn端用到的图片放置在res目录下。即–bundle-output 后面的参数和–assets-dest后面的参数可以自定义的。我们在命令行终端执行yarn android命令,即可生成main.bundle。
      在这里插入图片描述

    这样,我们就完成了rn端环境的搭建了。现在,我们来写下rn页面的代码来测试下。首先,我们新建一个src文件夹,用来存放我们缩写的rn代码。如下所示:
    在这里插入图片描述
    然后,我们在src建立一个HelloWorld.tsx文件。

    import React from "react";
    import {StyleSheet, Text, View} from "react-native";
    
    
    
    const styles = StyleSheet.create({
        container: {
            // flex: 1,
            justifyContent: 'center',
            alignItems:'center'
        },
        hello: {
            fontSize: 20,
            textAlign: 'center',
            margin: 10
        }
    });
    
    export class HelloWorld extends React.Component {
        render() {
            return (
                <View style={styles.container}>
                       
                        <Text>{"setData"}</Text>
    
                </View>
            );
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    然后,在index.js文件中添加如下代码

    import React from 'react';
    import {AppRegistry,} from 'react-native';
    import {HelloWorld} from "./src/view/HelloWorld";
    
    //如果原生端想要引用rn端的控件,则必须要使用registerComponent方法注册,如果单纯只是给rn端使用,那么就不必使用registerComponent方法注册。
    //例如:我们原生想要调用HelloWorld这个rn组件,那么原生就必须通过“MyReactNativeApp”这个键找到HelloWorld这个控件,如果HelloWorld只是被rn端的其他ts文件引用,那么就不必在这里注册了
    AppRegistry.registerComponent(
        'MyReactNativeApp',//这个名字可以随便定义,但是必须是字符串
        () => HelloWorld
    );
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样,我们rn端的第一个页面就写好了。

    • 原生环境搭建(进阶)
      首先,我们要自定义一个application,该application需要实现ReactApplication接口。
    package com.example.demo;
    
    import android.app.Application;
    import android.content.Context;
    import com.facebook.soloader.SoLoader;
    
    /**
     * Created by Brett.li on 2021/9/21.
     */
    public class MyReactApplication extends Application implements ReactApplication {
        @Override
        public ReactNativeHost getReactNativeHost() {
           return new ReactNativeHost(this) {
                @Override
                public boolean getUseDeveloperSupport() {
                    return BuildConfig.DEBUG;
                }
    
                @Override
                protected List<ReactPackage> getPackages() {
                    return new PackageList(this).getPackages();
                }
    
                @Nullable
                @Override
                protected String getBundleAssetName() {
                //就是我们打包出来的bundle的名字,不能写错,不然就加载不到bundle
                    return "main.bundle";//bundle的名字,默认是index.android.bundle
                }
    
                @Override
                protected String getJSMainModuleName() {
                    //即打包脚本中--entry-file后面的参数名。不能写错
                    return "index";
                }
            };
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            SoLoader.init(this, /* native exopackage */ false);
        }
    }
    //application中需要做两件事
    //1.实现getReactNativeHost接口
    //2.添加SoLoader.init(this, /* native exopackage */ false);这句代码
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    接着,我们在activity做如下修改:

    
    public class MainActivity extends AppCompatActivity {
        private BaseRNActivityDelegate mDelegate;
    
        protected BaseRNActivityDelegate createReactActivityDelegate() {
            return new BaseRNActivityDelegate(this, "MyReactNativeApp");//表示,我们要加载MyReactNativeApp所对应的rn控件
        }
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mDelegate = createReactActivityDelegate();
            mDelegate.onCreate( savedInstanceState);
        }
    
    //ReactActivityDelegate其实就是个代理,这个类里面帮助我们做了大量的工作,我们,只要在其构造方法中传入index.js中注册的控件的键名即可调用对应的控件。至于为什么要继承ReactActivityDelegate类,是因为该类里面很多方法都是protected的,我们根本不能直接调用
        class BaseRNActivityDelegate extends ReactActivityDelegate{
    
            public BaseRNActivityDelegate(Activity activity, @Nullable String mainComponentName) {
                super(activity, mainComponentName);
            }
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    这样,我们运行程序,MainActivity页面就能够加载到HelloWorld.tsx文件里面的内容了。
    在这里插入图片描述

    记得要修改androidManifest.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.demo">
    
        <uses-permission android:name="android.permission.INTERNET" />
    
        <application
            android:name=".MyReactApplication"
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/Theme.Demo"
            android:usesCleartextTraffic="true">
            
            <activity android:name=".MainActivity"
                android:exported="true">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
        </application>
    
    </manifest>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    好了,到这里我们已经基本搭建好了rn的环境的。后面,笔者会继续讲解如何封装原生的代码的。

  • 相关阅读:
    常见问题(系统、软件、代码等故障):解决方法——总结学习
    HMM代码参数
    js基础知识整理之 —— 变量和数据类型
    oracle分组合并数值带顺序
    Boost研究:Boost Log
    26.在springboot中使用thymeleaf判断语句(if,switch)
    DataGrip连接MySQL
    《 Python List列表全实例详解系列(五)》——修改元素(修改单个、修改一组)
    Acwing/3359. 更多奇怪的照片
    神经网络如何识别图像,神经网络图像识别技术
  • 原文地址:https://blog.csdn.net/qq_36828822/article/details/127398891