在使用了 Provider 一年后,遇到了很多阻力,期间尝试过 BLoC 、MobX ,均不如意,一个样本代码太多,使用复杂,一个生产代码要等很久。难道 Flutter 就没有诸如原生 Android 的 jetpack 套装一样方便的套件吗?后来开始尝试 GetX,才发现真香,正如作者所说:
GetX是Flutter的超轻便且强大的解决方案。它以快速实用的方式结合了高性能状态管理,智能依赖性注入和路由管理。
我写了一个demo探索过了基本使用方式之后,又决定写一个 待办清单app 实践一下 Clean Architecture 。
首先感谢下鸿洋大佬的 todo api,第一版是利用 api 开发的一个在线应用,后来在不注册的情况下,加入 moor 数据库,可以离线使用。这一部分改的仓促,下一期迭代会改进。
项目依赖和结构
dependencies:
flutter:
sdk: flutter
cookie_jar: ^1.0.1
cupertino_icons: ^1.0.0
date_format: ^1.0.9
dio: ^3.0.10
dio_cookie_manager: ^1.0.0
dio_http_cache: ^0.2.11
flutter_slidable: ^0.5.7
get: ^3.21.2
google_fonts: ^1.1.1
moor: ^3.4.0
path: ^1.7.0
path_provider: ^1.6.24
pull_to_refresh: ^1.6.3
shared_preferences: ^0.5.12+4
table_calendar: ^2.3.1
项目网络模块封装了 dio,因为是 带 cookie 的 请求,所以加入了 cookie 和本地化,算是一个比较完善的请求模块。
数据库选用了 moor ,Android 中 room 的字母倒过来就是这个,和 room 一样可以响应式,十分优秀。
剩下的第三方包就是分页和侧滑控件,还有一个日历包。
整体项目的结构参考getx_pattern,又按照自己的习惯做了修改。
从 GetX 开始开发
使用 GetX
void main() async {
runApp(GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/',
builder: (context, child) => Scaffold(
// Global GestureDetector that will dismiss the keyboard
body: GestureDetector(
onTap: () {
hideKeyboard(context);
},
child: child,
),
),
theme: appThemeData,
defaultTransition: Transition.fade,
getPages: AppPages.pages,
initialBinding: SplashBinding(),
home: SplashPage(),
));
}
命名路由
要使用完整的路由功能,需要把 MaterialApp 替换为 GetMaterialApp ,中间加入的builder 是为了解决点击空白处隐藏键盘的需求,这个在原生也很常见。
static final pages = [
GetPage(
name: Routes.LOGIN,
page: () => LoginPage(),
binding: LoginPageBinding(),
),
GetPage(
name: Routes.SPLASH,
page: () => SplashPage(),
binding: SplashBinding(),
),
GetPage(
name: Routes.SIGN_UP,
page: () => SignUpPage(),
binding: SiginUpBinding(),
),
GetPage(
name: Routes.TASK,
page: () => TaskPage(),
binding: TaskBinding(),
),
GetPage(
name: Routes.TASK_ADD,
page: () => AddTaskPage(),
binding: AddTaskBinding(),
),
GetPage(
name: Routes.TASK_DETAILS,
page: () => TaskDetailsPage(),
),
GetPage(
name: Routes.TASK_EDIT,
page: () => EditTaskPage(),
binding: EditTaskBinding(),
),
GetPage(
name: Routes.TASK_MOTHLY,
page: () => MonthlyPage(),
binding: MonthlyBinding(),
),