前段时间第一次尝试写Flutter项目,公司的一个小APP,不过麻雀虽小,五脏俱全,接下来就简单讲讲整个完成过程、代码架构、技术选型吧,这里做个记录,方便以后回顾。
AI强势开局
这个项目需要适配Android与iOS端,且指定Flutter开发。我是Android开发者,第一次接触Flutter,没有学习,直接拿AI完成环境配置、编码。我用的是TRAE,买了Pro包月,性价比挺高的。TRAE的IDE可以直接打开项目目录,它会以项目为上下文,可以更加精准地理解我们的命令。
首先编辑器用 Android Studio,因为更加熟悉。开局先让AI自己创建一个Flutter项目,并自行安装好Flutter环境,然后给AS安装Flutter和Dart的插件。可以指定下Flutter的安装目录,不要装在项目里,当然装错也没事,让AI改就行。疑难杂症都抛给AI,真的效率太高了。
因为要跑iOS,所以用的是mac电脑,运行iOS应用需要安装xCode,安装xCode之前需要升级系统到最新版,安装完xCode后再下载最新的iOS模拟器即可,然后就可以从AS里面直接启动模拟器了。
运行App的话需要在xCode配置BundleId,随意写个喜欢的ID,苹果不像安卓一样要手动写到项目内,注意不用付年费就可运行App,但是如果要实现苹果推送就要充个开发者会员了。
项目架构
目录结构
作为新手,先看下Flutter项目的目录结构:
- android - 包含 Android 特定的文件
- ios - 包含 iOS 特定的文件
- assets - 静态资源,如图片、字体、JSON文件等
- lib - Dart代码,flutter核心代码,main.dart 为程序运行入口文件
- test - 测试文件
- pubspec.yaml - 配置文件,管理第三方依赖、图片、字体等资源
- gromore_ads - 本地引入的一个flutter插件
核心库
下面是一些常用库,主要也是参考了GitHub中的优秀Demo项目 github.com/simplezhli/…
gromore_ads:
path: ./gromore_ads
# Toast插件 https://github.com/OpenFlutter/flutter_oktoast
oktoast: ^3.4.0
# 网络库 https://github.com/cfug/dio
dio: ^5.9.0
# Dart 常用工具类库 https://github.com/Sky24n/common_utils
common_utils: 2.1.0
# WebView插件 https://github.com/flutter/packages/tree/main/packages/webview_flutter
webview_flutter: 4.13.0
# 快捷存储 https://juejin.cn/post/6844903873262387207
sp_util: 2.0.3
# 格式化String https://github.com/Naddiseo/dart-sprintf
sprintf: ^7.0.0
# 获取当前设备信息 https://github.com/fluttercommunity/plus_plugins/tree/main/packages/device_info_plus
device_info_plus: 12.2.0
# 路由框架 https://github.com/theyakka/fluro
fluro: ^2.0.5
# 图片缓存 https://github.com/renefloor/flutter_cached_network_image
cached_network_image: ^3.4.0
# 下拉刷新
easy_refresh: ^3.4.0
# 网络状态 https://github.com/fluttercommunity/plus_plugins/tree/main/packages/connectivity_plus
connectivity_plus: ^6.0.5
Flutter的Dio和Android的OkHttp很像,功能强大支持自定义拦截器,用起来也是很丝滑的。还有Flutter各种跳转用路由框架fluro也很方便,也有统一的生命周期方法(didPush、didPop等)。这里建议先了解下程序入口「main.dart」的相关代码,学习下「MaterialApp」的相关参数。把APP的启动流程捋清楚,可以事半功倍。
页面架构
关于页面代码的完成,都是直接将UI出的界面丢给AI,AI会完成一个基本的、丑丑的界面,然后自己一点点优化,当然,也可以不断输入命令让AI一直改。网络请求、架构分层这些,都可以让AI写,把核心信息给AI即可。下面看下AI写的代码。
架构选型时,页面架构在getX与RiverPod中选择了后者,RiverPod遵循响应式编程,整个代码写下来非常舒服,和Compose的写法很像了。举个例子,收藏页面,首先也是把界面信息封装成一个「state」:
这个页面里是一个列表,支持下拉刷新、上拉加载更多、编辑模式,编辑模式下可以多选,相关变量都集中在了「CollectionState」中了,「CollectionsNotifier」会持有state对象,然后提供一个provider供界面监听,在界面中使用「select」进行精细化监听:(CollectionScreen就是收藏界面)
当界面初始化时触发「initState」,这里调用「CollectionsNotifier」的fetchInitial获取数据,获取后修改state就会自动触发界面变化了:
这里网络/数据库/mock数据请求都单独写在了另一层代码中,总共三层代码,整体代码就很方便阅读,fetchInitial会调用到queryCollections:
Flutter里面也是可以写页面的基础类的,不过这里是用「with」继承:
这个基础类我封装了Progress相关方法:
mixin BasePage<T extends ConsumerStatefulWidget> on ConsumerState<T> {
bool _isShowDialog = false;
void closeProgress() {
if (mounted && _isShowDialog) {
_isShowDialog = false;
NavigatorUtils.goBack(context);
}
}
void showProgress() {
/// 避免重复弹出
if (mounted && !_isShowDialog) {
_isShowDialog = true;
try {
showDialog<void>(
context: context,
barrierDismissible: false,
barrierColor: const Color(0x00FFFFFF),
// 默认dialog背景色为半透明黑色,这里修改为透明(1.20添加属性)
builder: (_) {
return WillPopScope(
onWillPop: () async {
// 拦截到返回键,证明dialog被手动关闭
_isShowDialog = false;
return Future.value(true);
},
child: buildProgress(),
);
},
);
} catch (e) {
/// 异常原因主要是页面没有build完成就调用Progress。
debugPrint(e.toString());
}
}
}
/// 可自定义Progress
Widget buildProgress() => const ProgressDialog(hintText: '正在加载...');
}
这里面也可以重写页面生命周期,可以统一实现一些需求。有一点要吐槽下,Flutter的private变量居然是用下划线前缀标记,很特别。
与Android/iOS原生代码互相请求
/// 原生调Flutter
static void setup() {
final channel = MethodChannel(AppConfig.deviceInfoChannel);
channel.setMethodCallHandler((MethodCall call) async {
if (call.method == _methodOnToken) {...}
}
}
/// Flutter调原生
static Future<void> startCellularRestrictedStateListener() async {
try {
final platform = MethodChannel(AppConfig.deviceInfoChannel);
await platform.invokeMethod(_methodStartCellularListen);
} on PlatformException catch (e) {
Log.e('startCellularRestrictedStateListener error: ${e.message}');
}
}
以上代码都是AI生成,直接输入相关命令,AI会完成很漂亮的代码。
END
最后,AI很强大,可以让我们从0开始,让我们能迅速学会相关知识,但是完成项目也需要更精准的AI命令,需要人与AI的不断磨合,最后才能完成一个精准实现的APP。真正实践的过程中,还是要人下场修改代码的,所以使用AI的过程也是学习的过程,需要最终能读懂AI的代码。还有,使用AI时建议结合git一起使用,能很好的对每次修改进行review。
以上,记录一下,欢迎批评指正,各种交流。