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']
};
//在metro.config.js文件中copy下面这段代码
module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

细心的同学一定发现了上图中有一个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"
  ]
}

具体细节,感兴趣的同学可以查阅相关的资料,我们这里就不介绍了。
接着,我们还需要更改的一个文件就是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"
  }
}

更改后:

{
  "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"
  }
}

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

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

当我们在命令行终端执行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. 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>
        );
    }
}

然后,在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
);

这样,我们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);这句代码

接着,我们在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);
        }
    }
}

这样,我们运行程序,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>

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值