最近买了一本书,ReactNative开发原生应用,以前都是直接使用Kotlin开发,但是感觉最近一直写JS,不如用JS开发
吧,然后就边看书边开发了,写了一个简单的语音天气APP,基本上该遇到的坑和功能都使用了,tips:应用很小,所以没有使用Redux.
ReactNative和一些套壳的框架相比好多了,编译后是原生的代码,这个就是很有意思了,还能和原生混合开发.
前排提示一个很坑的问题:RN0.6开始拆分了特定平台的组件到公共库里了,比如android的Toolbar,你直接在React-native引入是没用的.需要专门安装,一会会提到.
看看成品吧,会在酷安上架哦,我的酷安ID:IWH暖
本文总的结构如下:
1.安装RN环境并解决一些坑
2.开始编写android应用并使用android特定的组件
3.打包APK,精简体积,签名,发布应用.
安装RN脚手架
yarn global add react-native-cli
创建项目
react-native init demo
如果创建项目特别慢,甚至出现网络超时,更换yarn源
yarn config set registry https://registry.npm.taobao.org -g
yarn config set sass_binary_site http://cdn.npm.taobao.org/dist/node-sass -g
启动项目,报错没有命令的,查看自己是否全局安装了.
react-native run-android
为了预览与调试,你需要一个模拟器,我这里是直接用的android手机开启USB调试.
使用 ADB devices 看看有没有你的设备.
如果你没有安装android的SDK工具,会报错,你要安装好SDK(如果你用了androidStudio,那么进入demo项目的android目录
项目android/local.properties
追加 sdk.dir = /sdk目录 linux /home/userName/android...
如果你遇到license错误
android 许可错误
进入sdk目录的 Sdk/tools/bin 执行 ./sdkmanager --licenses 同意许可...
建议也检查以下你的bash配置,尤其是用ZSH的同学..
nano ~/.bash_profile
export ANDROID_HOME=/home/qiuguo/Android/Sdk
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/platform-tools/adb
如果手机设备出现 服务连接失败,一般都是没启动服务
项目根目录 yarn start 即可,注意默认端口8081不要被其他应用用了.或者你可以摇晃设备弹出调试菜单,手动更改ip与地址,然后
adb reverse tcp:8081 tcp:8081 来自定义
如果你遇到资源文件出错,或者未找到,执行以下命令
react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/sr
c/main/assets/index.android.bundle --assets-dest android/app/src/main/res/
既然可以预览了,那我们开始编写应用了.
编写前,其实我画了一个简单的原型图
查看原型演示:布谷天气墨刀原型演示
这里不会讲解React如何编写,只说说RN的东西
看一下初始化的项目的结构:其中Android是RN编译后的原生目录
看到有 APP.js Index.js 这两个是入口文件,其他的和平时一样,自己创建组件目录或者资源目录就行了和web开发一样.
看看index.js这是入口,其中registerComponent()是不是很熟悉,和web开发里面.APP是我们的最外层组件
/**
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
import React from 'react';
//style.js 是一个json格式的css样式
import {APP_STYLE} from './styles';
//导入常用组件
import {
SafeAreaView,
StyleSheet,
ScrollView,
Modal,
ToastAndroid,
View,
Animated,
TouchableNativeFeedback,
Touchable,
RefreshControl,
TouchableHighlight,
Image,
Text,
NativeEventEmitter,
StatusBar,
} from 'react-native';
//这里是初始化项目自带的引导组件,你可以删除掉
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
//组件
class App extends React.Component {
state = {
isSpeaching: false,
helpStatus: false,
refresh:false,
voiceText: '',
//是否选择地区
isSelect: false,
//语音状态
voiceHide: true,
//天气信息
weatherData: {},
};
....
....
//样式使用styles
render(){
return(
//你也可以直接使用行内写法
)
}
}
//创建样式表对象
const styles = StyleSheet.create(APP_STYLE);
export default App;
const APP_STYLE ={
weatherBig: {
fontSize: 70,
marginTop: 30,
marginLeft: 30,
zIndex: 99
}
}
1.你应该注意到了,全是驼峰写法,格式是json格式,这里有一个可能会遇到的困惑,就是 层级显示,用两个:Zindex和Elevation在android里面.
其中 elevation优先.这个也是原生Android里面的z方向,会出现阴影,具体css你可以去RN官方文档查看哦,这里提一下默认的布局,你可以使用position为relative和absolute,不可以用fixed,还有就是RN的基础组件,如View这个组件,都是使用Flexbox,但是又有区别,比如,你想让子组件填充父组件,设置父组件 Flex:1 就行了.其他属性比如width支持百分比,记得加引号.
2.样式基本了解后,我们看看如何编写事件
和web有区别的是你需要在以下的组件内部编写按压事件
TouchableNativeFeedback
Touchable
TouchableHighlight
关闭说明书
3.引入公共组件,看原型,好像我们用到了一个toolbar组件,如果你在React-native引入,会发现,无法使用,百度一圈,都是从rn包导入,那都是旧的版本,新版本你需要额外安装新的toolbar包
facebook公共组件仓库 这里有额外的所有包,如video,netInfo等,这里演示一个toolbar,如果你的RN是0.6 不需要使用link ,网上说link是旧版的.
yarn add @react-native-community/toolbar-android
然后就可以愉快的使用了.
布谷天气语音版
4. 使用Gif与图片资源
上面的代码里会发现用的 require().这里提一下一个坑,RN不支持路径使用动态拼接,也就是说你没有办法使用变量拼接!
然后我们处理GIF的问题
进入android/app/目录 找到 gradle文件 在dependencis 添加依赖
implementation 'com.facebook.fresco:animated-gif:2.0.0'
一些小伙伴发现图片不动,升级你的依赖,网上很多都是旧的..
5.使用权限管理
android有一些权限是需要申请使用的,fb也提供了在上面的公共库里哦,用法,这里不说了,提一句就是,没开发过Android的小伙伴经常会忘记在manifest文件声明权限!
6.使用存储
如果你用AsyncStorage 会遇到警告,因为它也被剥离出来了,你需要专门安装哦
这里是一个封装片段
async setData(key,value){
try{
await AsyncStorage.setItem(key,value);
console.log('保存数据成功.')
return true;
}catch (e) {
console.log('保存错误:' + e)
return false;
}
},
7.使用网络
RN使用默认支持Fetch,你也可以用axios,不过很遗憾jQuery不可以,因为它有涉及DOM的功能...
注意RN不存在跨域的,你可以看看postman就知道了.
8.动画 等有空再写.
下面说说最重要的一项,打包APK出来,因为主要是说说遇到的错误,至于如何生成你的开发者秘钥,请自行百度哦,因为我以前用AndroidStudio开发应用,所以有一个jks的文件,如果你用的命令行创建会有好几个文件.
配置你的秘钥,进入android/app/gradle.properties 设置几个变量,一会要用到的.jks文件也是在同级目录
android.useAndroidX=true
android.enableJetifier=true
MYAPP_RELEASE_STORE_FILE=xxx.jks
MYAPP_RELEASE_KEY_ALIAS=xx
MYAPP_RELEASE_STORE_PASSWORD=xx
MYAPP_RELEASE_KEY_PASSWORD=xxx
然后修改构建文件
android/app/build.gradle
找到这个块,替换
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
然后进入android根目录
执行./gradlew assembleRelease
Rn打包的时候,会经常遇到以下错误,资源文件重复,部分依赖包出错(比如本应用使用的讯飞语音SDK,由于gradle不兼容,总是报错),正常来说,打包后,资源文件重复,要么是你的资源文件重名了,要么就是你打包之前,没有clean build后的项目.
资源文件重复后,如果你执行了clean也是一样,手动把app/build/genera... 删除
进入 android目录执行 ./gradlew clean 清理项目,再次 ./gradlew assembleRelease 构建APK
当你打包后,你会发现,安装包非常大,不到1000行的代码有30M,因为RN默认打包了全平台版本,你可以自己选择是否支持其他平台
我们修改一下 gradle文件 我只保留了arm架构版本,不过也生成一个通用的安装包,单独版本的大小现在是10M左右
def enableSeparateBuildPerCPUArchitecture = true
...
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk true // If true, also generate a universal APK
include "armeabi-v7a","arm64-v8a"
}
}
...
universalApk true
最后最重要的提示就是:一定要看清楚自己的RM版本,构建APK失败,先Clean一下,如果是第三方SDK可以去看看依赖包的gradle...
...等待更新
公众号:秋果科技工作室
酷安ID:IWH暖 来玩啊