01.Flutter入门
Flutter 介绍
什么是 Flutter?
Flutter 是 Google 推出的一套开源跨平台 UI 框架,可以快速地在 Android、iOS 和 Web 平台上构建高质量的原生用户界面。同时,Flutter 还是 Google 新研发的 Fuchsia 操作系统的默认开发套件。在全世界,Flutter 正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。Flutter 采用现代响应式框架构建,其中心思想是使用组件来构建应用的 UI。当组件的状态发生改变时,组件会重构它的描述,Flutter 会对比之前的描述,以确定底层渲染树从当前状态转换到下一个状态所需要的最小更改。
Flutter 环境搭建
- Android Studio/Android SDK/JDK (安装目录尽量不要有带空格的或有中文字符的路径)
- AS 插件 Flutter/Dart
- 下载 Flutter SDK 和 Dart SDK(安装了 Flutter SDK 后,就不需要再安装 Dart SDK 了)
- 离线下载:Flutter SDK 并安装,不要安装在有空格的路径
- 在线下载,在国内需要配置镜像
MacOS 配置到
~/.zshrc
: export PUB_HOSTED_URL=https://pub.flutter-io.cn export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn git clone -b dev https://github.com/flutter/flutter.git Windows 就配置到环境变量
- 配置 Flutter 环境变量 Windows
Windows
- 配置环境变量
FLUTTER_HOME=D:\Program Files\flutter_windows_3.7.12-stable\flutter
- 配置 PATH:
%FLUTTER_HOME%\bin
Mac
- 配置到
~/.zshrc
export FLUTTER_HOME=~/Flutter
(你安装 FLutter SDK 的路径)export PATH=$FLUTTER_HOME/bin:$PATH
\
- 检测 Flutter 是否安装成功
flutter –version
- 检测安装环境问题及安装慢的问题
flutter doctor (运行以下命令查看是否有依赖关系需要安装以完成设置,此命令检查环境并向终端窗口显示报告。首次运行 flutter 命令时,它会自动下载自己的依赖项并进行编译) 配置了
PUB_HOSTED_URL
和FLUTTER_STORAGE_BASE_URL
后执行 flutter doctor 效果:flutter doctor 检测出来的环境问题:
- 解决 flutter doctor 问题(Windows)
- Android toolchain 问题
flutter doctor –android-licenses 如果执行了上面的命令还是提示错误: Android sdkmanager not found. Update to the latest Android SDK and ensure that the cmdline-tools are installed to resolve this. 就需要在 SDKManager 中勾选下面去下载,安装过程中需要输入几次 y
原因是非英语的 windows 系统会出现,切换到 master channel 就可解决: flutter upgrade flutter channel master
Android SDK file not found
必须安装 Android SDK tools,尽管其状态显示为 obsolete 废止。
Unable to find bundled Java version
有人说新建一个文件夹 jre 把 jbr 中的内容都 copy 到 jre 中;直接建一个软链不就好了?
ln -s /Applications/Android\ Studio.app/Contents/jbr /Applications/Android\ Studio.app/Contents/jre
如果安装了 Preview,也需要加 ln -s /Applications/Android\ Studio\ Preview.app/Contents/jbr /Applications/Android\ Studio\ Preview.app/Contents/jre
- iOS toolchain 问题
brew update brew install –HEAD usbmuxd brew link usbmuxd brew install –HEAD libimobiledevice brew install ideviceinstaller
flutter config –android-studio-dir=”/Applications/AndroidStudioBeta0622.app”
Flutter 常用命令
- 查看 flutter 版本:
flutter --version
- 诊断 flutter 安装环境:
flutter doctor
- 安装 flutter app:
flutter run
Flutter 组成
Flutter 分为三大部分:由 Dart 语言负责的 Framework 层;Dart 语法执行器;Skia 图像处理引擎。Flutter 也可以理解为开发 SDK 或者工具包,其通过 Dart 作为开发语言,并且提供 Material 和 Cupertino 两套视觉控件,视图或其他和视图相关的类,都以 Widget 的形式表现。Flutter 有自己的渲染引擎,并不依赖原生平台的渲染。Flutter 还包含一个用 C++ 实现的 Engine,渲染也是包含在其中的。
Flutter 优缺点
优点:
- 热重载(Hot Reload) 利用 Android Studio 直接一个 ctrl+s 就可以保存并重载,模拟器立马就可以看见效果,相比原生冗长的编译过程强很多
- 一切皆为 Widget 对于 Flutter 来说,手机应用里的所有东西都是 Widget,通过可组合的空间集合、丰富的动画库以及分层课扩展的架构实现了富有感染力的灵活界面设计;
- 借助可移植的 GPU 加速的渲染引擎以及高性能本地代码运行时以达到跨平台设备的高质量用户体验。简单来说就是:最终结果就是利用 Flutter 构建的应用在运行效率上会和原生应用差不多。
缺点:
- 不支持热更新
- 三方库有限,需要自己造轮子
- Dart 语言编写,增加了学习难度,并且学习了 Dart 之后无其他用处,相比 JS 和 Java 来说;Dart 语言是套娃式的,可读性差
Flutter 和 RN 对比?
Flutter 调试效率高,性能好,有自绘引擎,包大小劣于 RN
RN 的优势在于包体积较小,动态化以及局部动态化比较好,但因为没有自绘引擎,长列表表现劣于 Flutter
Flutter 工程目录
Flutter application 目录
- android:安卓原生工程配置相关文件,包括应用图标,原生资源,权限配置等
- ios:iOS 原生工程配置相关文件,熟悉 iOS 开发的会知道具体的用途,其中 最主要的是 Runner 下,设置到原生的配置,如最关键的 InfoPlist 文件,以及权限相关的配置,这些配置建议在 Xcode 中配置会更为直观。
- build:打包输出文件,主要是安卓打包文件,iOS 打包需要通过 Xcode 完成。
- lib:最重要的目录,所有源码都在这个目录,其中 main.dart 是入口文件,而 main 方法是入口方法。
- test:测试相关文件
- web:Flutter 2.0 引入的,支持三端统一的 web 端文件
- pubspec.yaml:这个文件十分重要,所有的第三方依赖,以及文件依赖都通过这个文件管理,类似与苹果的 podfile 和安卓的 gradle 文件。
- pubspec.lock
.gitignore
文件 What not to commit
Flutter module 目录
pubspec.lock 是否提交到 git
pubspec.lock
file is a special case, similar to Ruby’s Gemfile.lock
。
- 如果是 regular packages,不要提交该文件到 git;重新生成该文件测试你的 packages 是否兼容最新的依赖
- 如果是 application packages,推荐提交该文件;用来跟踪
dependencies
,每次的dart pub upgrade
或者pubspec.yaml
文件变更都会更改pubspec.lock
文件
fvm
flutter 多版本切换
fvm
简介
FVM 的全称是 Flutter Version Management,一个 CLI 管理器,用于 Flutter 多版本的管理。官方网站:fvm.app
Mac OS版本安装
brew 方式:
1
2
3
4
5
6
7
# install
brew tap leoafarias/fvm
brew install fvm
# uninstall
brew uninstall fvm
brew untap leoafarias/fvm
设置 fvm 的环境变量:
1
2
3
4
### fvm管理多个Flutter版本
export FVM_HOME=$HOME/fvm
export FLUTTER_ROOT=$FVM_HOME/default
export PATH=~/fvm/default/bin:$PATH
使用
设置 sdk 安装目录
fvm config 设置一下 flutter sdk 保存的位置,如果不配置,在 mac 下的默认目录是在 ~/fvm
1
fvm config --cache-path <flutter sdk path>
修改后可以使用 fvm config
查看一下是否设置成功了
常用的命令
fvm releases 查看可使用的版本;fvm releases tail -10 列举 10 条记录 - fvm install x.x.x 安装 x.x.x 版本
- fvm remove x.x.x 删除某个的版本
- fvm list 查看已安装列表
- fvm global x.x.x 设置全局版本
- fvm use x.x.x 单独设置某个项目运行的版本
Android Studio 配置
配置 git 忽略文件
在配置了 fvm 以后,在.fvm 目录下会有一个 flutter_sdk 的链接文件,这个文件是不需要上传 git 的,否则会有冲突,在.gitignore 文件中过滤一下。
/.fvm/flutter_sdk /.fvm/fvm_config.json
遇到的问题
Waiting for another flutter command to release the startup lock
Waiting for another flutter command to release the startup lock… Flutter 2.0.6 • channel stable • https://github.com/flutter/flutter.git Framework • revision 1d9032c7e1 (2 years, 6 months ago) • 2021-04-29 17:37:58 -0700 Engine • revision 05e680e202 Tools • Dart 2.12.3
- go to the flutter root folder
- delete
<flutter folder>/bin/cache/lockfile
(3.13.7 版本删除的是.upgrade_lock
) - run pub get
Caused by: java.lang.IllegalStateException: Transform’s input file does not exist
未找到原因,后面配置了 fvm 就可以了
BUG! exception in phase 'semantic analysis' in source unit '_BuildScript_' Unsupported class file major version 61
问题:
原因:JDK 版本过高,61 是 JDK 17,降级为 JDK 11
在 .android gradle.properties
添加:
1
org.gradle.java.home=/Users/10082146/Library/Java/JavaVirtualMachines/corretto-11.0.19/Contents/Home
Flutter 遇到的问题
AS 设置 flutter SDK 报错
原因:还有些东西没下载下来
解决:执行下 flutter run,再设置
dart 版本问题
项目要求的是 dart 是不需要 null safety,而本机安装的是 dart 3.1.0
使用 which flutter 和 which dart 查看命令位置
安装 dart 的命令:
1
2
brew tap dart-lang/dart # dart https://dart.dev/get-dart#install
brew install dart
解决:
1
brew uninstall dart
Flutter 插件 Android 模块中的报红且无法打包的问题
- 配置了 Flutter 的 sdk
1
2
sdk.dir=D:\\android\\SDK
flutter.sdk=D:\\flutter_windows_3.7.12-stable\\flutter
- 在
android/build.gradle
文件中,编写读取flutter.sdk
的代码,最后使用compileOnly files
依赖本地的 flutter 库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
//获取flutter的sdk路径
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
println "Flutter SDK not found. Define location with flutter.sdk in the local.properties file."
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
compileOnly 'androidx.annotation:annotation-jvm:+'
compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
compileOnly 'androidx.annotation:annotation:1.5.0'
}
- Android Studio 打开 Flutter 中的 Android 目录下的工程
did not have a source.properties
将 SDK/ndk 下的 source.properties 拷贝到 SDK/ndk-bundle 中去
Flutter 网络导致的问题
一般是代理导致的,比如 ClashX,有几种现象
flutter pub get 卡死
Flutter attach 不生效
flutter module attach 不生效,一直在重试 Exception attempting to connect to the VM Service
[+1608 ms] Exception attempting to connect to the VM Service: SocketException: Connection failed, address = 127.0.0.1, port = 54966 [ ] This was attempt 44. Will retry in 0:00:01.600000. [+1605 ms] Exception attempting to connect to the VM Service: SocketException: Connection failed, address = 127.0.0.1, port = 54966 [ ] This was attempt 45. Will retry in 0:00:01.600000. [+1604 ms] Exception attempting to connect to the VM Service: SocketException: Connection failed, address = 127.0.0.1, port = 54966 [ ] This was attempt 46. Will retry in 0:00:01.600000. [+1602 ms] Exception attempting to connect to the VM Service: SocketException: Connection failed, address = 127.0.0.1, port = 54966 [ ] This was attempt 47. Will retry in 0:00:01.600000.
flutter run -v 报错
解决
- 设置 Flutter 镜像
1
2
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
- 一般是网络问题,检查代理
原因: 使用了 Proxifier+ClashX
,导致全局代理被固定You have JVM property "https.proxyHost" set to "127.0.0.1"
解决 1:去除 ~/.gradle/gradle.properties
下的 http/https
代理
解决 2:终端命令: 用于删除 http 代理端口
JAVA_OPTS="$JAVA_OPTS -DsocksProxtPort"
- 删除缓存重启
AS->File->invalitDate Caches/Restart
解决 2:在 IDEA 中的 Help - Edit Custom VM Options 添加以下配置:
1
2
3
4
5
6
-Dhttp.proxyHost
-Dhttp.proxyPort
-Dhttps.proxyHost
-Dhttps.proxyPort
-DsocksProxyHost
-DsocksProxyPort
解决 3:上面做了还不行,就重启电脑
解决 4:检查你的代理软件,是不是开启了全局代理
- Proxifier+ClashX 给退出,这里是把 Proxifier 退出就可以了,ClashX 不退出即使设置成 Global 也可以
Flutter 学习路线
Dart 语言
见 [[Dart基础]]
Flutter 组件
需要熟悉 Flutter 框架提供的自带组件,然后可以通过自带的组件组合成为自己的自定义组件。
见 [[Flutter基础组件]]
Flutter 自带的组件
表单
自定义组件
状态管理
状态管理是 Flutter 的核心,如何处理数据实体、业务逻辑、界面之间的关系对代码的可维护性十分关键,而这都依赖于状态管理的实现。
- 有状态组件和无状态组件的区别,阅读
StatefulWidget
和StatelessWidget
的源码 - 理解组件的渲染机制:当应用状态管理插件时,我们通过渲染机制能够知道状态数据更新时如何减少刷新的范围,实现局部刷新,从而提升性能。
- 主流状态插件应用:对比主流状态插件,从中选择一个合适自己团队的应用。对于长期用的状态管理插件,建议深入了解具体的实现机制,以便再遇到问题时能够快速定位,快速解决。
- 按需刷新:相比
setState
这种简单粗暴的全局更新,状态管理插件的一大优势就是可以实现局部刷新。通过按需刷新可以极大地提高页面的流畅度。