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/;
},
- 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的环境的。后面;笔者会继续讲解如何封装原生的代码的。
加载全部内容