1.2 逻辑、页面、数据 分离 MVVM 架构
职责:
View 视图显示
Controller 控制器,大管家,各种生命周期、数据装备、路由…
DataModel 数据模型
ViewModel 负责数据发生变化时去更新 View 视图
getx + dio + mvvm
说明:
View 视图中加载控制器 Controller
控制器 Controller 生命周期载入数据
View 视图触发控制器 Controller 方法改变数据
数据 ViewModel 触发更新视图
Model 数据模型拉取远程数据或者本地数据
分层代码生成与理解
第 1 步: 创建 login 模块
通过右键 “Getx: Full Page” 创建一个 login 的模块
我们创建了一个 login 的模块,文件清单如下
1 2 3 4 5 6 7 8 9 ├── login │ ├── bindings.dart │ ├── controller.dart │ ├── index.dart │ ├── state.dart │ ├── view.dart │ └── widgets │ ├── hello.dart │ └── widgets.dart
文件说明
名称
说明
index.dart
导包
controller.dart
控制器 业务逻辑
state.dart
数据
view.dart
视图
bindings.dart
路由懒加载
widgets
子组件
可以发现通过这样的方式,将代码的层级关系进行了拆分,需要维护哪里就哪里,不会混乱写的到处都是,适合团队开发。
第 2 步: 阅读理解代码 state.dart
1 2 3 4 5 6 7 8 import 'package:get/get.dart' ;class LoginState { final _title = "" .obs; set title(value) => _title.value = value; get title => _title.value; }
controller.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import 'package:get/get.dart' ;import 'index.dart' ;class LoginController extends GetxController { LoginController(); final state = LoginState(); void handleTap(int index) { Get.snackbar( "标题" , "消息" , ); } @override void onInit() { super .onInit(); } @override void onReady() { super .onReady(); } @override void onClose() { super .onClose(); } @override void dispose() { super .dispose(); } }
view.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import 'package:flutter/material.dart' ;import 'package:get/get.dart' ;import 'index.dart' ;import 'widgets/widgets.dart' ;class LoginPage extends GetView <LoginController > { const LoginPage({Key? key}) : super (key: key); Widget _buildView() { return const HelloWidget(); } @override Widget build(BuildContext context) { return GetBuilder<LoginController>( builder: (_) { return Scaffold( appBar: AppBar(title: const Text("login" )), body: SafeArea( child: _buildView(), ), ); }, ); } }
bindings.dart
1 2 3 4 5 6 7 8 9 10 import 'package:get/get.dart' ;import 'controller.dart' ;class LoginBinding implements Bindings { @override void dependencies() { Get.lazyPut<LoginController>(() => LoginController()); } }
widgets/hello.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import 'package:flutter/material.dart' ;import 'package:get/get.dart' ;import '../index.dart' ;class HelloWidget extends GetView <LoginController > { const HelloWidget({Key? key}) : super (key: key); @override Widget build(BuildContext context) { return Center( child: Obx(() => Text(controller.state.title)), ); } }
在绑定路由时, binding 中加入你的模块依赖
1 2 3 4 5 GetPage( name: RouteNames.login, page: () => const LoginPage(), binding: LoginBinding(), ),
创建路由 lib/common/routers/pages.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import 'package:flutter_woo_commerce_getx_learn/pages/system/login/index.dart' ;import 'package:get/get.dart' ;class RoutePages { static List <GetPage> list = [ GetPage( name: "/" , page: () => const LoginPage(), binding: LoginBinding(), ), ]; }
lib/main.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class MyApp extends StatelessWidget { const MyApp({Key? key}) : super (key: key); @override Widget build(BuildContext context) { return GetMaterialApp( title: 'Flutter Demo' , theme: ThemeData( primarySwatch: Colors.blue, ), initialRoute: "/" , getPages: RoutePages.list, ); } }
修改 login lib/pages/system/login/controller.dart
1 2 3 4 5 6 7 8 9 class LoginController extends GetxController { LoginController(); final state = LoginState(); void onTap(int index) { state.title = '点击了第$index 个按钮' ; }
lib/pages/system/login/view.dart
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Widget _buildView() { return Center( child: Column( children: [ const HelloWidget(), ElevatedButton( onPressed: () { controller.onTap(DateTime .now().microsecondsSinceEpoch); }, child: const Text("点击" ), ), ], ), ); }
提交代码到 git
1 2 git add . git commit -m "逻辑、数据、视图 分离"