Android端ReactNative环境搭建——下
作者:快盘下载 人气:67接着上文;原生模块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/; },
- start是我们调试代码用到的。后面会讲解如何使用这个功能。
- 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的环境的。后面;笔者会继续讲解如何封装原生的代码的。
加载全部内容