Flutter 中的 MVVM 架构实现指南

本文首发于公众号:移动开发那些事:Flutter 中的 MVVM 架构实现指南

1 MVVM架构

MVVM (Model-View-ViewModel) 是一种软件架构模式,它是 MVC(Model-View-Controller)MVP(Model-View-Presenter)的进化版本, 它将应用程序的用户界面(UI)逻辑与业务逻辑分离,通过 ViewModel 作为中间层连接 ViewModel

1.1 核心组件

  • Model:负责数据处理、业务逻辑和网络请求等,不直接与UI交互;
  • ViewUI 界面,负责展示数据和接收用户输入,通过与ViewModel的绑定来进行UI的更新;
  • ViewModel:连接 ViewModel 的桥梁,处理视图逻辑并提供数据给View

1.2 架构特点

  • 双向数据绑定ViewViewModel 之间的数据变化会自动同步,减少了手动更新 UI 的代码;
  • 提高可测试性ViewModel 可以独立测试,无需依赖UI
  • 分离关注点:UI 逻辑和业务逻辑分离,提高代码可维护性和可测试性。
  • 提高可维护性:代码的可读性和可维护性更高,适合大型复杂项目的开发;

1.3 适用场景

  • 复杂 UI 应用:当界面逻辑复杂时,MVVM 能有效管理状态和数据流;
  • 需要频繁更新 UI 的应用:双向数据绑定使数据更新更高效;
  • 需要单元测试的项目ViewModel 的独立性使其易于测试;

2 简单架构示例

以一个简单的计数器的例子来说明如何来搭建一个MVVM的架构;

php 复制代码
import 'package:flutter/material.dart';

// 步骤1:定义 Model: 负责数据处理
class CounterModel {
  int _count = 0;
  
  int get count => _count;
  
  void increment() {
    _count++;
  }
  
  void decrement() {
    _count--;
  }
}

// 步骤2:ViewModel: 连接 View 和 Model
class CounterViewModel with ChangeNotifier {
  final CounterModel _model = CounterModel();
  
  int get count => _model.count;
  
  void increment() {
  	// 处理数据更新
    _model.increment();
    notifyListeners(); // 通知 View 更新
  }
  
  void decrement() {
  	// 处理数据更新
    _model.decrement();
    notifyListeners(); // 通知 View 更新
  }
}


// 步骤3 View: UI 界面
class CounterScreen extends StatelessWidget {
  final CounterViewModel _viewModel = CounterViewModel();
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('MVVM 计数器')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 使用 ValueListenableBuilder 监听 ViewModel 变化,viewModel变化时,对应的页面也会同步刷新
            ValueListenableBuilder(
              valueListenable: _viewModel,
              builder: (context, value, child) {
                return Text(
                  '计数: ${_viewModel.count}',
                  style: TextStyle(fontSize: 24),
                );
              },
            ),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: _viewModel.decrement,
                  child: Text('减'),
                ),
                SizedBox(width: 20),
                ElevatedButton(
                  onPressed: _viewModel.increment,
                  child: Text('加'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

3 使用GetX框架实现MVVM架构

GetX 是 Flutter 中一个强大的轻量级框架,它简化了状态管理、路由和依赖注入等功能。下面是使用 GetX 实现相同计数器应用的示例:

php 复制代码
import 'package:flutter/material.dart';
import 'package:get/get.dart';

// 步骤1:定义 Model: 负责数据处理
class CounterModel {
  int _count = 0;
  
  int get count => _count;
  
  void increment() {
    _count++;
  }
  
  void decrement() {
    _count--;
  }
}

// 步骤2:ViewModel (在 GetX 中称为 Controller)
class CounterController extends GetxController {
  final CounterModel _model = CounterModel();
  
  // 使用 RxInt 实现响应式数据
  final RxInt _count = 0.obs;
  
  int get count => _count.value;
  
  void increment() {
    _model.increment();
    _count.value = _model.count; // 更新响应式数据
  }
  
  void decrement() {
    _model.decrement();
    _count.value = _model.count; // 更新响应式数据
  }
}

// 步骤3 : View: UI 界面
class CounterScreen extends StatelessWidget {
  // 使用 Get.put() 初始化 Controller
  final CounterController _controller = Get.put(CounterController());
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('GetX MVVM 计数器')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 使用 Obx 监听 Controller 中的响应式数据
            Obx(() => Text(
                  '计数: ${_controller.count}',
                  style: TextStyle(fontSize: 24),
                )),
            SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: _controller.decrement,
                  child: Text('减'),
                ),
                SizedBox(width: 20),
                ElevatedButton(
                  onPressed: _controller.increment,
                  child: Text('加'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

4 适用场景

场景类型 推荐方案 原因
小型应用/快速原型 GetX 开发速度快,代码少
中大型项目 原生 + Provider 分层明确,长期维护性强
多平台代码共享 原生 + 抽象ViewModel 业务逻辑与平台解耦
高频更新 GetX 性能优化,避免全页重建

5 总结

MVVM 架构模式在 Flutter 开发中非常有用,它可以帮助我们构建更清晰、更易维护的应用程序。在不使用第三方框架的情况下,我们可以通过ChangeNotifierStream 等机制实现 MVVM,但代码会相对复杂。而使用 GetX 这样的框架可以大大简化 MVVM 的实现,提供更简洁的代码和更好的开发体验。实际使用过程中,可以根据业务的复杂程度,团队熟练度,以及长期计划来决定使用哪个机制来实现MVVM架构;

6 参考文献

相关推荐
提子拌饭1332 分钟前
开源鸿蒙跨平台Flutter开发:AR厨艺教学应用
android·flutter·华为·开源·ar·harmonyos·鸿蒙
FelixBitSoul4 分钟前
彻底吃透 React Hook:它背后的执行模型到底是什么? 🚀
前端
Huanzhi_Lin11 分钟前
Nginx本地资源服务器-常用脚本
服务器·前端·nginx·batch·静态资源服务器
weixin1997010801611 分钟前
《好看视频商品详情页前端性能优化实战》
前端·性能优化·音视频
有意义12 分钟前
深入理解浏览器存储方案:从Cookie到JWT登录认证
前端·面试·浏览器
jiayong2312 分钟前
第 6 课:第二轮真实重构,拆出任务表格组件
前端·重构
jiayong2319 分钟前
第 4 课:怎么把一个大页面拆成多个组件
运维·服务器·前端
2401_8396339122 分钟前
Flutter 框架跨平台鸿蒙开发 - 家庭食谱传承系统
flutter·华为·harmonyos
skywalk816322 分钟前
使用DuMate帮助创建 Python 3.9 环境并部署 Kotti CMS
前端·chrome
世人万千丶24 分钟前
开源鸿蒙跨平台Flutter开发:步数统计应用
学习·flutter·华为·开源·harmonyos·鸿蒙