こんにちは、テルプロです!
「MVVMをRiverpodで実装する方法は?」とお悩みではないでしょうか。
本記事ではそんな悩みを解決していきます!
- MVVMの基本設計をサンプルで理解できる
- Riverpod + freezedの使い方がわかるようになる
- コードを公開しているので、自分の環境で確かめることができる
MVVMをRiverpodで実装する【サンプル】
事前準備
パッケージをインストール
今回使用するパッケージは以下の通りです。
dependencies:
build_runner: ^2.1.8
flutter:
sdk: flutter
flutter_riverpod: ^1.0.3
freezed: ^1.1.1
freezed_annotation: ^1.1.0
dev_dependencies:
flutter_lints: ^1.0.0
flutter_test:
sdk: flutter
プロジェクト構成
リポジトリ構成
完成イメージ
今回実装するアプリは、数字が2つあり、数字をクリックすると値が(+1)されていき、ボタンをクリックすると値が(0)になるというシンプルなアプリです。
それでは、MVVMでこちらのアプリを作っていきましょう!
ソースコード
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_mvvm/view/home_page.dart';
void main() {
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter MVVM',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
model / home_page_state.dart
まずは、モデルとなるクラスを作成していきましょう。
今回は「mainCount」と「subCount」という2つの値を用意します。
クラスの作成にはfreezedを使用しています。freezedを使用することで、不変クラスを作成することが出来ます。
import 'package:flutter/foundation.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
// 生成されるファイル名を指定する( `生成元ファイル名.freezed.dart` )
part 'home_page_state.freezed.dart';
@freezed
class HomePageState with _$HomePageState {
const factory HomePageState({
@Default(0) int mainCount,
@Default(0) int subCount,
}) = _HomePageState;
}
上記の内容が書き終わったら、こちらのコマンドを回してください。
flutter pub run build_runner watch --delete-conflicting-outputs
これにより、ファイルが自動生成されます。–delete-conflicting-outputsを加えることで、クラスに変更が加えられる度に再生成されます。
modelフォルダが上記のようになっていれば問題ありません。これで、データを保持するクラスを用意することが出来ました。
view_model / home_page_notifier.dart
次に「View」と「Model」を紐つける役割を担う「ViewModel」を作成していきます。
状態管理にはRiverpodを使用しています。Riverpodを使用することで値をグローバル定数として宣言できるため、どのWidgetからもデータを取得できます。
操作内容をStateNotifierにまとめ、StateNotifierProviderで状態を管理します。
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_mvvm/model/home_page_state.dart';
class HomePageNotifier extends StateNotifier<HomePageState> {
// 初期値の指定
HomePageNotifier() : super(const HomePageState());
// メインカウントを+1する
void increaseMainCount() async {
state = state.copyWith(mainCount: state.mainCount + 1);
}
// サブカウントを+1する
void increaseSubCount() async {
state = state.copyWith(subCount: state.subCount + 1);
}
// すべてのカウントを0に戻す
void resetAllCount() async {
state = state.copyWith(
mainCount: 0,
subCount: 0,
);
}
}
// HomePageNotifierの状態を管理する
final homePageProvider =
StateNotifierProvider.autoDispose<HomePageNotifier, HomePageState>(
(ref) => HomePageNotifier(),
);
view / home_page.dart
最後に、サンプルアプリのUI(見た目)を作っていきます。
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_mvvm/model/home_page_state.dart';
import 'package:flutter_mvvm/view/home_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mvvm/view_model/home_page_notifier.dart';
class HomePage extends ConsumerWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
// state(状態)
final _homePageState = ref.watch(homePageProvider);
// provider(状態の操作)
final _homePageNotifier = ref.watch(homePageProvider.notifier);
return Scaffold(
appBar: AppBar(title: const Text('Flutter MVVM')),
floatingActionButton: FloatingActionButton(
onPressed: _homePageNotifier.resetAllCount,
child: const Icon(Icons.exposure_zero),
),
body: ListView(
children: [
ListTile(
title: Text('Main Count ${_homePageState.mainCount}'),
onTap: _homePageNotifier.increaseMainCount,
),
ListTile(
title: Text('Sub Count ${_homePageState.subCount}'),
onTap: _homePageNotifier.increaseSubCount,
),
],
),
);
}
}
大変お疲れ様でした!以上でアプリは完成です!
今回ご紹介したアプリ全体のソースコードはこちらです。
よろしければ、ご参考にどうぞ。
GitHub:https://github.com/terupro/flutter_mvvm
まとめ
今回は「MVVMをRiverpodで実装する方法」を解説しました。
今回紹介したMVVMは、Flutterを用いたアプリ開発で主流となっている設計方法です。良ければ上記のコードを参考に、色々と試してみてください。
▼以下では、私の実体験に基づいて「Flutterの効率的な勉強法」の具体的な手順を詳しく解説しています。よろしければ、ご参考にどうぞ!
最後までご覧いただきありがとうございました。ではまた!
参考文献
Riverpod 2.0 – Complete Guide (Flutter Tutorial)