MVVM 架构

MVVM 全称 Model–View–ViewModel,是一种常见的软件架构模式,最早由微软提出,用于简化 UI 与业务逻辑的分离。
它主要解决的问题是:如何把界面(View)和逻辑(Model)解耦,让代码更清晰、可维护性更高
Model(模型层)
- 负责数据和业务逻辑。
- 包括 网络请求、数据库操作、本地缓存、业务规则 等。
- 不关心界面,只负责提供数据。
View(视图层)
- 负责 UI 展示。
- 只负责展示,不写业务逻辑。
- 通过 数据绑定 或 观察者模式 来自动更新 UI。
ViewModel(视图模型层)
- View 与 Model 之间的桥梁。
- 核心职责:
- 从 Model 获取数据;
- 对数据进行处理(格式化、逻辑转换);
- 暴露给 View,方便直接展示;
- 处理用户交互(调用 Model 的方法)。
getx + dio + mvvm
三者关系

GetX:是状态管理 + 路由管理 + 依赖注入 框架。在 MVVM 中主要承担 ViewModel 层 的角色:
- 管理状态(
Rx
响应式变量); - 接收 View 的事件;
- 通知 View 更新。
GetX 是 实现 MVVM 中 ViewModel 的工具。
Dio:是Flutter 中最流行的 网络请求库。在 MVVM 中属于 Model 层:
- 请求接口;
- 处理 JSON;
- 返回数据给 ViewModel。
Dio 是 实现 MVVM 中 Model 的工具。
View (Flutter Widget)
↑ 观察/绑定状态
ViewModel (GetX Controller)
↑ 调用/依赖注入
Model (Dio + Repository + 数据类)
Model 层(使用 Dio 请求接口)
// user_model.dart
class User {
final String name;
final int age;
User({required this.name, required this.age});
factory User.fromJson(Map<String, dynamic> json) {
return User(name: json['name'], age: json['age']);
}
}
// user_repository.dart
import 'package:dio/dio.dart';
import 'user_model.dart';
class UserRepository {
final Dio _dio = Dio();
Future<List<User>> fetchUsers() async {
final response = await _dio.get('https://api.example.com/users');
return (response.data as List)
.map((json) => User.fromJson(json))
.toList();
}
}
ViewModel 层(GetX 管理状态)
// user_controller.dart
import 'package:get/get.dart';
import 'user_repository.dart';
import 'user_model.dart';
class UserController extends GetxController {
final UserRepository repository;
UserController(this.repository);
var users = <User>[].obs;
var isLoading = false.obs;
void loadUsers() async {
isLoading.value = true;
try {
users.value = await repository.fetchUsers();
} finally {
isLoading.value = false;
}
}
}
View 层(UI 使用 GetX 绑定状态)
// user_page.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'user_controller.dart';
import 'user_repository.dart';
class UserPage extends StatelessWidget {
final UserController controller = Get.put(UserController(UserRepository()));
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Users")),
body: Obx(() {
if (controller.isLoading.value) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: controller.users.length,
itemBuilder: (context, index) {
final user = controller.users[index];
return ListTile(
title: Text(user.name),
subtitle: Text("Age: ${user.age}"),
);
},
);
}),
floatingActionButton: FloatingActionButton(
onPressed: controller.loadUsers,
child: Icon(Icons.refresh),
),
);
}
}