刚开始接触用 Flutter
开发App的时候,比较喜欢它的 UI
编写方式,尤其是 Flutter
热重载特性,UI调试如同Web前端开发,能够即时查看代码更改的效果。那在日常开发中,还有没有其它提升工作效率的方法呢,今天就给大家分享几个超实用的建议,助你在 Flutter
开发中事半功倍。
1. 使用 Code Snippets
如果之前做过原生的 iOS
或者 Android
再来写 Flutter
代码的时候,Flutter
在代码提示上会不习惯,比如 for
循环,Flutter
的代码提示是 foreach
或者 for(var a in arr)
这些。
List<String> items = ["Flutter", "iOS", "Android"];
items.forEach((element) {
print(element);
});
// 或者
for (var element in items) {
print(element);
}
当我们需要数组的索引的时候,就需要手写一遍:
for (int i = 0; i < items.length; i++) {
var element = items[i];
print(element);
}
这个时候我们可以这些常用的代码保存到自己的 Code Snippets
中,具体操作根据编辑器不同而不同,这里以 Android Studio
为例,Setting -> Editor -> Live Templates。
使用的时候输入:fori
编辑器就会有提示,选中回车后就是保存的Code Snippets
,是不是很方便。
2. 使用代码生成器
开发过程中有大量重复的代码或者操作,这个时候使用代码生成器可以自动生成重复性的代码,减少开发人员手动编写模板代码的工作量。这样可以节省大量的时间和精力,并使开发人员能够更专注于解决业务逻辑和UI设计等核心任务。不同于Code Snippets
需要依赖编辑器的设置,这生成的代码则使用插件或者工具来完成。
下面是我经常使用的代码生成器插件或者工具:
-
flutter_gen
:项目图片资源、字体、颜色等的代码生成器。
使用Widget build(BuildContext context) { return Image.asset('assets/images/profile.jpeg'); }
flutter_gen
之后,显示图片的时候再也不需要填入字符串了。Widget build(BuildContext context) { return Assets.images.profile.image(); }
-
intl_utils
:Intl
库样板代码生成器,用于在 .arb 文件的翻译和 Flutter 应用程序之间创建绑定。
使用Text(AppLocalizations.of(context)!.translate('intl_zh')),
intl_utils
生成的模板代码:Text( S.of(context).intl_zh, style: const TextStyle( color: Color(0xFFffffff), fontSize: 22), )
-
ftool:我自己开发的一款
JSON
字符串转成Dart Model
生成器工具。
其它的还有很多,如:Bloc Generator
、Provider Generator
等状态管理相关的模板代码生成器,我就不在这里一一列举了。
3. 应用图标生成
Flutter
应用图标需要支持多个平台,如果每一张不同尺寸的图标都去手动切的话,太麻烦,这里推荐一个插件工具 flutter_launcher_icons
,只需要几个配置就可以自动生成各个平台的应用图标。
dependencies:
flutter_launcher_icons: ^0.13.1
flutter_icons:
image_path: "images/image.png"
android: true
ios: true
#image_path_ios: "images/image.png"
#image_path_android: "images/image.png"
命令行工具里执行下面命令就可以了。
flutter pub run flutter_launcher_icons
如果你还是觉得麻烦,不想引入这个插件,可以使用在线工具,网上也有很多。
4. CI/CD
持续集成(CI
)和持续交付(CD
)在开发过程中的好处有很多,特别是对于使用 Flutter
做跨平台开发 App
来说,如果用传统手动的方式打包提测那就太耗时间了,CI/CD
可以做快速地构建和部署应用程序,节省宝贵的时间也最大限度地减少人为错误,
团队开发更是如此,能确保所有团队成员都在同一个一致的构建环境中工作,这有助于避免由于环境差异而导致的问题。我们常使用工具有 Fastlane
,它在 Flutter
项目中的详细用法以后抽个时间会专门写一篇文章来介绍。
5. 清晰的应用架构
不管是大型还是小型的 Flutter
应用,一个清晰的应用架构设计也是不可或缺的,尤其是在团队开发的时候,每个人项目经验、代码风格各不相同,如果碰上项目赶工期的话,那写出来的除了本人其它人都看不懂,时间久了有可能他自己也看不懂了。这时候,清晰的应用架构使团队成员之间更容易合作和协同工作。每个人都可以清楚地了解项目的结构和设计,从而更好地分工合作,提高开发效率。
你可能会说应用架构的设计和使用并不是很简单和直接,甚至还有些繁琐,怎么能提升开发效率?关于 Flutter
应用架构的设计和实践相关的疑问,可以翻一翻我之前的两篇文章:《Flutter大型项目架构:状态管理篇》 和 《Flutter大型项目架构:分层设计篇》,也许你会从中找到答案。
6. 依赖注入
说到依赖注入那就不得不提 get_it
,在 Flutter
开发里知名度高使用人数众多,那它是如何做依赖管理的呢?我在 get_it
的官方文档找到了这句话。
it’s a way to decouple the interface (abstract base class) from a concrete implementation, and at the same time allows to access the concrete implementation from everywhere in your App over the interface.
大概意思就是:它是一种将接口(抽象基类)与具体实现解耦的方法,同时允许通过接口从应用程序中的任何位置访问具体实现。
Flutter
中是不支持反射的,而大多数传统的 IoC
容器要依赖于反射,get_it
的作者就借鉴了 .Net
中的服务定位器(ServiceLocator
)的概念,并运用到了 Flutter
中,相比于传统的 IoC
容器,get_it
更加轻量简洁。
我们怎么使用 get_it
呢?get_it
文档写的很详细了,但本篇文章介绍另外一种使用方法,就是和 injectable
插件一起使用,下面是简单的示例用法。
abstract class Repository {
Future<void> login({
required String email,
required String password,
});
}
@LazySingleton(as: Repository)
class RepositoryImpl implements Repository {
@override
Future<void> login({
required String email,
required String password,
}) async {
// 登录操作,发送网络请求
}
}
命令行运行:flutter packages pub run build_runner build
命令后,就会自动生成以下代码:
import 'package:get_it/get_it.dart' as _i1;
import 'package:injectable/injectable.dart' as _i2;
extension GetItInjectableX on _i1.GetIt {
// initializes the registration of main-scope dependencies inside of GetIt
Future<_i1.GetIt> init({
String? environment,
_i2.EnvironmentFilter? environmentFilter,
}) async {
final gh = _i2.GetItHelper(
this,
environment,
environmentFilter,
);
gh.lazySingleton<_i3.Repository>(() => _i4.RepositoryImpl());
return this;
}
}
业务层调用:
@Injectable()
class LoginBloc extends BaseBloc<LoginEvent, LoginState> {
LoginBloc(this._repository) : super(LoginState()) {
on<LoginButtonPressed>(
_onLoginButtonPressed,
transformer: log(),
);
}
final Repository _repository;
FutureOr<void> _onLoginButtonPressed(LoginButtonPressed event, Emitter<LoginState> emit) {
_repository.login(email: "", password:"");
}
}
上面代码中以发送登录请求为例,在业务层使用的直接调用抽象类 Repository
的 login
函数,而具体实现则在 RepositoryImpl
中,很好的隔离业务层和数据处理层,使得他们之间的连接都是通过抽象层 Repository
,这中间的依赖关系不再需要你写任何代码,get_it
配合 injectable
帮你生成了,这样管理和解耦应用程序的组件更加方便了,特别是跨组件调用的时候,提高代码的可维护性、可测试性和灵活性。
7. Github Copilot
一款由 GitHub
和 OpenAI
共同开发的人工智能代码编写助手,它基于 GPT
模型生成代码建议,可以根据上下文和用户输入提供代码提示和建议,帮助开发者快速编写代码。还能能够生成函数、类、变量声明等各种类型的代码片段,并提供自然语言描述的文档注释。
用过的就不需要我多说了吧,好用是真好用,就是有点儿小贵(对于小编来说),初学者使用它简直太香了,可以直接把 Copilot
作为学习工具,用来学习编程语言和编码风格。
以上与插件相关的内容着重在提升效率的说明上,详细用法还是要去阅读官方文档。以上建议是小编在开发过程中经常使用到的,也仅代表我个人的观点,当然还有更多其它提升效率的方法。好了,本篇文章分享就到这里,感谢您的阅读,原创不易,记得关注加点赞哦。