Flutter MVVM架构插件riverpod_mvvm的使用

Flutter MVVM架构插件riverpod_mvvm的使用

开始使用

本项目是一个新的Flutter项目,专注于MVVM架构,并使用了riverpod_mvvm插件来简化开发流程。该插件提供了平台特定的实现代码,适用于Android和iOS。

对于想要开始使用Flutter进行开发的朋友,可以参考以下资源:

  • Flutter官方文档,其中包含了教程、示例代码以及移动应用开发指南和完整的API引用。

示例代码

以下是一个简单的示例,展示了如何使用riverpod_mvvm插件来构建一个具有MVVM架构的应用。

import 'package:flutter/material.dart';
import 'package:riverpod_mvvm/riverpod_mvvm.dart';
import 'package:riverpod_mvvm_example/second_page.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(
    const ProviderScope(
      child: MaterialApp(
        home: MyApp(),
      ),
    ),
  );
}

class MyApp extends StatefulView<MyAppViewModel, int> {
  const MyApp({super.key});

  @override
  ViewState<MyAppViewModel, int> createState() => _MyAppState();
}

class _MyAppState extends ViewState<MyAppViewModel, int> with MyAppUiActions {
  @override
  initViewModel() {}

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: InkWell(
          onTap: () {
            read.moveToSecond();
          },
          child: const Icon(Icons.exit_to_app_sharp),
        ),
        title: const Text('示例'),
      ),
      body: Center(
        child: Text(
          '$watch',
          style: const TextStyle(fontSize: 32),
        ),
      ),
      floatingActionButton: FloatingActionButton.large(
        onPressed: () {
          read.increase();
        },
        child: const Icon(Icons.add),
      ),
    );
  }

  @override
  MyAppViewModel get read => ref.read(myAppViewModel.notifier);

  @override
  int get watch => ref.watch(myAppViewModel);

  @override
  moveToSecondPage() {
    Navigator.of(context)
        .push(MaterialPageRoute(builder: (context) => const SecondPage()));
  }
}

mixin MyAppUiActions {
  moveToSecondPage();
}

final myAppViewModel = StateNotifierProvider<MyAppViewModel, int>((ref) => MyAppViewModel(0));

class MyAppViewModel extends StateNotifier<int> with ViewModel<MyAppUiActions> {
  MyAppViewModel(super.state);

  increase() {
    state++;
  }

  moveToSecond() {
    state = 0;
    uiActions.moveToSecondPage();
  }
}

代码解释

  1. main函数:

    void main() {
      WidgetsFlutterBinding.ensureInitialized();
    
      runApp(
        const ProviderScope(
          child: MaterialApp(
            home: MyApp(),
          ),
        ),
      );
    }
    

    这里初始化了WidgetsFlutterBinding并设置了MaterialApp的初始页面为MyApp

  2. MyApp类:

    class MyApp extends StatefulView<MyAppViewModel, int> {
      const MyApp({super.key});
    
      @override
      ViewState<MyAppViewModel, int> createState() => _MyAppState();
    }
    

    MyApp继承自StatefulView,定义了一个状态管理器_MyAppState

  3. _MyAppState类:

    class _MyAppState extends ViewState<MyAppViewModel, int> with MyAppUiActions {
      @override
      initViewModel() {}
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            leading: InkWell(
              onTap: () {
                read.moveToSecond();
              },
              child: const Icon(Icons.exit_to_app_sharp),
            ),
            title: const Text('示例'),
          ),
          body: Center(
            child: Text(
              '$watch',
              style: const TextStyle(fontSize: 32),
            ),
          ),
          floatingActionButton: FloatingActionButton.large(
            onPressed: () {
              read.increase();
            },
            child: const Icon(Icons.add),
          ),
        );
      }
    
      @override
      MyAppViewModel get read => ref.read(myAppViewModel.notifier);
    
      @override
      int get watch => ref.watch(myAppViewModel);
    
      @override
      moveToSecondPage() {
        Navigator.of(context)
            .push(MaterialPageRoute(builder: (context) => const SecondPage()));
      }
    }
    

    _MyAppState类实现了ViewStateMyAppUiActions,通过readwatch方法来访问和监听状态变化。

  4. myAppViewModel:

    final myAppViewModel = StateNotifierProvider<MyAppViewModel, int>((ref) => MyAppViewModel(0));
    

    定义了一个StateNotifierProvider来管理状态。

  5. MyAppViewModel类:

    class MyAppViewModel extends StateNotifier<int> with ViewModel<MyAppUiActions> {
      MyAppViewModel(super.state);
    
      increase() {
        state++;
      }
    
      moveToSecond() {
        state = 0;
        uiActions.moveToSecondPage();
      }
    }
    

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

1 回复

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


riverpod_mvvm 是一个基于 Flutter 的状态管理插件,它结合了 RiverpodMVVM 架构模式,帮助开发者更好地组织和管理 Flutter 应用的状态。RiverpodProvider 的改进版,而 MVVM (Model-View-ViewModel) 是一种常见的架构模式,用于分离 UI 逻辑和业务逻辑。

1. 安装 riverpod_mvvm

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

dependencies:
  flutter:
    sdk: flutter
  riverpod: ^2.0.0
  riverpod_mvvm: ^1.0.0

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

2. 基本概念

riverpod_mvvm 中,MVVM 架构通常由以下几部分组成:

  • Model: 负责数据的获取和处理。
  • View: 负责 UI 的展示。
  • ViewModel: 作为 ViewModel 之间的桥梁,处理业务逻辑并将数据转换为 View 可用的状态。

Riverpod 用于管理和提供这些状态。

3. 创建 Model

假设我们有一个简单的 UserModel,它负责从 API 获取用户数据:

import 'package:riverpod/riverpod.dart';

class UserModel {
  Future<String> fetchUser() async {
    // 模拟网络请求
    await Future.delayed(Duration(seconds: 2));
    return "User Data";
  }
}

final userModelProvider = Provider<UserModel>((ref) => UserModel());

4. 创建 ViewModel

ViewModel 负责调用 Model 中的方法,并管理 View 所需的状态:

import 'package:riverpod/riverpod.dart';
import 'package:riverpod_mvvm/riverpod_mvvm.dart';

class UserViewModel extends ViewModel {
  final UserModel _userModel;

  UserViewModel(this._userModel);

  AsyncValue<String> userState = const AsyncValue.loading();

  Future<void> fetchUser() async {
    userState = const AsyncValue.loading();
    try {
      final userData = await _userModel.fetchUser();
      userState = AsyncValue.data(userData);
    } catch (e) {
      userState = AsyncValue.error(e, StackTrace.current);
    }
  }
}

final userViewModelProvider = Provider<UserViewModel>((ref) {
  final userModel = ref.watch(userModelProvider);
  return UserViewModel(userModel);
});

5. 创建 View

View 中,我们使用 RiverpodConsumerConsumerWidget 来监听 ViewModel 的状态并更新 UI:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_mvvm/riverpod_mvvm.dart';

class UserPage extends ConsumerWidget {
  [@override](/user/override)
  Widget build(BuildContext context, WidgetRef ref) {
    final viewModel = ref.watch(userViewModelProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text('User Page'),
      ),
      body: Center(
        child: viewModel.userState.when(
          data: (userData) => Text(userData),
          loading: () => CircularProgressIndicator(),
          error: (error, stackTrace) => Text('Error: $error'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ref.read(userViewModelProvider).fetchUser();
        },
        child: Icon(Icons.refresh),
      ),
    );
  }
}

6. 运行应用

main.dart 中启动应用时,确保将 ProviderScope 包裹在应用的根 Widget 中:

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'user_page.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: UserPage(),
    );
  }
}
回到顶部