Flutter MVVM架构插件maac_mvvm的使用

Flutter MVVM架构插件maac_mvvm的使用

MVVM

maac_mvvm 是一个支持简单实现MVVM模式的包。该包不包含任何依赖注入框架。你可以选择任何你想要的依赖注入框架。它只有三个组件:ViewModel、StreamData 和 ViewModelWidget。

它简单、干净且非常易于实现。

特性

ViewModelWidget

ViewModelWidget 是一个构建UI小部件的地方,这些小部件将与ViewModel绑定。

ViewModel

ViewModel 负责自动处理初始化、恢复、暂停和销毁。

StreamData

StreamData 是一个有用的Stream包装器,用于更新UI,并在ViewModel生命周期销毁时自动取消订阅。

开始使用

安装

flutter pub add maac_mvvm

使用说明

1 - 安装包

flutter pub add maac_mvvm

2 - 创建你的ViewModel

以下是一个简单的ViewModel,用于从小部件增加计数器。

class ExamplePageViewModel extends ViewModel {
  ExamplePageViewModel();

  late final _uiState = 0.mutableData(this);
  late final uiState = _uiState.streamData;

  void increaseCounter() {
    _uiState.postValue(_uiState.data + 1); // 增加计数器值
  }
}

3 - 创建与ViewModel绑定的小部件

ViewModelWidget 只包含两个方法:createViewModel 和 build。

  • build 方法是构建界面的地方。
  • createViewModel 方法是初始化对应的ViewModel的地方。

我们不需要担心其他小部件的生命周期,因为它们会根据ViewModel自动调用。

class ExamplePage extends ViewModelWidget<ExamplePageViewModel> {
  const ExamplePage({Key? key}) : super(key: key);

  [@override](/user/override)
  ExamplePageViewModel createViewModel(BuildContext context) => ExamplePageViewModel();

  [@override](/user/override)
  Widget build(BuildContext context, ExamplePageViewModel viewModel) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            _buildCounterDisplay(viewModel),
            _buildButtonPlus(viewModel),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: viewModel.increaseCounter, // 绑定增加按钮的点击事件
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }

  Widget _buildButtonPlus(ExamplePageViewModel viewModel) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: ElevatedButton(
        onPressed: () {
          viewModel.increaseCounter();
        },
        child: const Text("+"),
      ),
    );
  }

  Expanded _buildCounterDisplay(ExamplePageViewModel viewModel) {
    return Expanded(
      child: Center(
        child: StreamDataConsumer<int>(
          streamData: viewModel.uiState,
          builder: (context, data) {
            return Text("You have pressed the button $data times.");
          },
        ),
      ),
    );
  }
}

4 - 监听ViewModel的数据变化

监听来自ViewModel的数据变化并使用StreamDataConsumer更新UI。

StreamDataConsumer 是一个监听数据流变化并相应地更新其UI的小部件。它可以用于从ViewModel显示数据并在数据变化时更新UI。

要使用StreamDataConsumer,首先需要在ViewModel中创建一个数据流。这可以通过使用StreamDataViewModel来完成。

一旦创建了数据流,可以将其作为参数传递给StreamDataConsumer小部件。StreamDataConsumer 将监听数据流的变化并相应地更新其UI。

例如,如果你在ViewModel中有一个计数器变量,你想在UI中显示它,可以为它创建一个StreamDataViewModel并传递给StreamDataConsumer小部件。每当计数器发生变化时,StreamDataConsumer 将更新其UI以显示新的值。

Expanded _buildCounterDisplay(ExamplePageViewModel viewModel) {
  return Expanded(
    child: Center(
      child: StreamDataConsumer<int>(
        streamData: viewModel.uiState,
        builder: (context, data) {
          return Text("You have pressed the button $data times.");
        },
      ),
    ),
  );
}

完整示例

class ExamplePage extends ViewModelWidget<ExamplePageViewModel> {
  const ExamplePage({Key? key}) : super(key: key);

  [@override](/user/override)
  ExamplePageViewModel createViewModel(BuildContext context) => ExamplePageViewModel();

  [@override](/user/override)
  Widget build(BuildContext context, ExamplePageViewModel viewModel) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text(
              'You have pushed the button this many times:',
            ),
            StreamDataConsumer<int>(
              builder: (context, data, child) {
                return Text(
                  '$data',
                  style: Theme.of(context).textTheme.headlineMedium,
                );
              },
              streamData: viewModel.uiState,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: viewModel.incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class ExamplePageViewModel extends ViewModel {
  ExamplePageViewModel();

  late final _uiState = 0.mutableData(this);
  late final uiState = _uiState.streamData;

  void incrementCounter() {
    _uiState.postValue(_uiState.data + 1);
  }
}

更多关于Flutter MVVM架构插件maac_mvvm的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter MVVM架构插件maac_mvvm的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用maac_mvvm插件来实现MVVM架构的代码示例。maac_mvvm是一个帮助实现Model-View-ViewModel架构模式的Flutter插件。

首先,确保你已经在pubspec.yaml文件中添加了maac_mvvm依赖:

dependencies:
  flutter:
    sdk: flutter
  maac_mvvm: ^最新版本号  # 请替换为实际可用的最新版本号

然后运行flutter pub get来安装依赖。

步骤 1: 创建Model

Model类通常用于存储数据。这里我们创建一个简单的User模型:

// models/user.dart
class User {
  final String name;
  final int age;

  User({required this.name, required this.age});
}

步骤 2: 创建ViewModel

ViewModel类用于处理业务逻辑和数据绑定。我们将使用maac_mvvm提供的BaseViewModel来创建我们的ViewModel。

// viewmodels/user_view_model.dart
import 'package:flutter/material.dart';
import 'package:maac_mvvm/maac_mvvm.dart';
import 'models/user.dart';

class UserViewModel extends BaseViewModel {
  User? _user;
  User? get user => _user;

  // 模拟获取用户数据的方法
  Future<void> fetchUserData() async {
    setBusy(true);
    await Future.delayed(Duration(seconds: 2)); // 模拟网络延迟
    _user = User(name: "John Doe", age: 30);
    notifyListeners(); // 通知视图更新
    setBusy(false);
  }
}

步骤 3: 创建View (Widget)

View层用于展示UI,并与ViewModel进行交互。我们将使用Provider来将ViewModel注入到Widget中。

// views/user_view.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'viewmodels/user_view_model.dart';

class UserView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final UserViewModel model = Provider.of<UserViewModel>(context);

    return Scaffold(
      appBar: AppBar(title: Text("User Info")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (model.isBusy)
              CircularProgressIndicator()
            else if (model.user != null)
              Column(
                children: [
                  Text("Name: ${model.user!.name}"),
                  Text("Age: ${model.user!.age}"),
                ],
              )
            else
              ElevatedButton(
                onPressed: model.fetchUserData,
                child: Text("Fetch User Data"),
              ),
          ],
        ),
      ),
    );
  }
}

步骤 4: 使用MultiProvider在应用顶层提供ViewModel

最后,在你的应用顶层使用MultiProvider来提供UserViewModel

// main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'viewmodels/user_view_model.dart';
import 'views/user_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserViewModel()),
      ],
      child: MaterialApp(
        title: 'Flutter MVVM Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: UserView(),
      ),
    );
  }
}

以上代码展示了如何在Flutter项目中使用maac_mvvm插件来实现一个简单的MVVM架构。UserViewModel处理数据获取和业务逻辑,UserView负责展示UI并与ViewModel进行交互,而User模型则存储用户数据。希望这个示例能帮助你理解如何在Flutter项目中使用MVVM架构。

回到顶部