Flutter MVVM架构插件onix_flutter_mvvm的使用

Flutter MVVM架构插件onix_flutter_mvvm的使用

该插件包含用于在Flutter中实现MVVM架构的基础类。

使用

视图模型(View Model)

创建视图模型类:

class MainViewModel extends ViewModel {
  int counter = 0;

  void increment() {
    counter++;
    notifyListeners(); // 通知监听器数据已更改
  }
}

当错误发生时,在视图模型中调用setError方法:

setError(Exception()); // 设置错误信息

在视图模型中触发单次事件(如显示对话框、导航等)时,调用setAction方法:

setAction(MyAction()); // 设置动作

在你的小部件状态中指定你的视图模型:

class _MyHomePageState extends ViewModelWidget<MyHomePage, MainViewModel>

在重写的createVm函数中创建你的视图模型实例:

[@override](/user/override)
MainViewModel createVm() => MainViewModel();

使用onError函数处理来自视图模型的错误(当调用setError时):

@Override
void onError(failure) {
  // 处理错误
}

使用onAction函数处理来自视图模型的动作(当调用setAction时):

@Override
void onAction(action) {
  if (action == MyAction) {
    context.goNamed('detailsScreen'); // 导航到详情屏幕
  }
  super.onAction(action);
}

使用viewModelBuilder构建器来处理视图模型的变化:

viewModelBuilder<MainViewModel>(builder: (context, vm) {
  return Text('${vm.counter}'); // 显示计数器值
}),

使用viewModelConsumer构建器来处理视图模型的变化:

viewModelConsumer<MainViewModel>(
  consumer: (context, vm) {
    // 执行你需要的操作
  },
  child: MyWidget(),
)

如果需要限制重建,请设置buildWhen参数:

buildWhen: (oldVm, newVm) {
  return oldVm.counter > newVm.counter;
},

带有状态的视图模型(Stateful View Model)

此选项设计用于带有附加模型类的所有变量的视图模型。所有使用方式保持不变,除了:

创建模型类:

class MainModel {
  final int counter;

  MainModel({this.counter = 0});

  MainModel copyWith({int? counter}) =>
      MainModel(counter: counter ?? this.counter);
}

将你的视图模型类扩展为ViewModelStateful<Model>

class MainViewModel extends ViewModelStateful<MainModel> {
  MainViewModel() : super(MainModel());

  void increment() {
    final newValue = data.counter + 1;
    setData(data.copyWith(counter: newValue)); // 更新数据
    notifyListeners(); // 通知监听器数据已更改
  }
}

在视图模型小部件中指定你的模型类型:

class _MyHomePageState extends ViewModelWidget<MyHomePage, MainViewModel>

在基于视图模型的小部件之外使用

向你的小部件添加相应的混合(mixin):

  • StateCommandMixin - 状态混合以访问命令构建器和消费者(commandBuildercommandConsumer);
  • StateViewModelMixin - 状态混合以访问视图模型构建器和消费者(vmBuildervmConsumer);
  • WidgetCommandMixin - 小部件混合以访问命令构建器和消费者(commandBuildercommandConsumer);
  • WidgetViewModelMixin - 小部件混合以访问视图模型构建器和消费者(vmBuildervmConsumer);

使用示例:

vmBuilder<MainViewModel>(
  builder: (context, vm) {
    return MyWidget();
  },
  viewModel: myViewModel,
)

命令(Commands)

在你的视图模型中添加命令,例如:

class MainViewModelCommands extends ViewModel {
  int counter = 0;

  late Command0<int> increment;

  MainViewModelCommands() {
    increment = Command0<int>(_increment); // 初始化命令
  }

  Future<Result<int>> _increment() async {
    await Future.delayed(const Duration(milliseconds: 500)); // 模拟异步操作
    counter++;
    return Result.ok(counter); // 返回成功结果
  }
}

使用commandBuilder来监听你的命令状态:

commandBuilder<int>(
  command: viewModel.increment,
  builder: (context, command) {
    if (command.running) {
      return const CircularProgressIndicator(); // 显示加载指示器
    }
    if (command.error) {
      return const Text('Error'); // 显示错误信息
    }
    return Text(
      '${command.result?.data ?? 0}', // 显示命令结果
      style: Theme.of(context).textTheme.headlineMedium,
    );
  },
)

在需要的地方执行命令:

void _onPressed() {
  viewModel.increment.execute(); // 执行命令
}

发现错误或有建议?请在此处报告:报告问题


示例代码

示例代码文件:main.dart

import 'package:example/base_vm_model_widget.dart';
import 'package:example/command_vm_widget.dart';
import 'package:example/stateful_vm_widget.dart';
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Expanded(child: BaseVMWidget()), // 基本视图模型小部件
            Divider(),
            Expanded(child: StatefulVMWidget()), // 带状态的视图模型小部件
            Divider(),
            Expanded(child: CommandVMWidget()), // 命令视图模型小部件
          ],
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何使用 onix_flutter_mvvm 插件来实现 Flutter MVVM 架构的示例代码。假设你已经在 Flutter 项目中添加了 onix_flutter_mvvm 依赖。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 onix_flutter_mvvm 依赖:

dependencies:
  flutter:
    sdk: flutter
  onix_flutter_mvvm: ^latest_version  # 请替换为实际最新版本号

2. 创建 ViewModel 类

ViewModel 是 MVVM 架构中的核心部分,负责处理业务逻辑和数据绑定。

import 'package:onix_flutter_mvvm/onix_flutter_mvvm.dart';
import 'dart:async';

class CounterViewModel extends BaseViewModel {
  int _count = 0;
  final _counterController = StreamController<int>.broadcast();

  Stream<int> get counterStream => _counterController.stream;

  void increment() {
    _count++;
    _counterController.sink.add(_count);
  }

  @override
  void dispose() {
    _counterController.close();
    super.dispose();
  }
}

3. 创建 View 层(UI)

View 层中,我们将使用 ViewModel 提供的数据来更新 UI。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:onix_flutter_mvvm/onix_flutter_mvvm.dart';
import 'counter_view_model.dart';  // 导入 ViewModel

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => CounterViewModel()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter MVVM Example'),
        ),
        body: Center(
          child: CounterView(),
        ),
      ),
    );
  }
}

class CounterView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterViewModel = Provider.of<CounterViewModel>(context);

    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text(
          'You have pushed the button this many times:',
        ),
        StreamBuilder<int>(
          stream: counterViewModel.counterStream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text(
                '${snapshot.data}',
                style: Theme.of(context).textTheme.headline4,
              );
            } else {
              return Text('0');
            }
          },
        ),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: () {
            counterViewModel.increment();
          },
          child: Text('Increment'),
        ),
      ],
    );
  }
}

4. 运行应用

确保所有文件都已正确保存,然后在你的终端中运行以下命令来启动应用:

flutter run

解释

  • ViewModel: CounterViewModel 管理状态并暴露一个 Stream 来通知 UI 更新。
  • View: CounterView 使用 StreamBuilder 来监听 ViewModel 的状态变化,并更新 UI。
  • Provider: 使用 provider 包来在 ViewViewModel 之间建立连接。

这个示例展示了如何使用 onix_flutter_mvvm 插件来实现一个简单的 Flutter MVVM 应用。你可以根据需求扩展这个示例,以适应更复杂的业务逻辑和 UI 交互。

回到顶部