[Flutter] DataFlowで状態管理してみる
この記事は2024年のFlutter Advent Calendar(カレンダー1)の17日目の記事です。
はじめに
皆さんは普段どんな状態管理の手法を使っていますか?
僕は未だにRiverpod(ver1)を使っています...(もういっそのことv2飛ばしてv3でもいいかもしれん)
今手伝っているプロダクトではGetXを使ってたりもします。
Flutterには様々な状態管理の手法があると思いますが、今回はDataFlow
という状態管理を紹介しようと思います。こういうものもあるんだという知るきっかけになってもらえれば!
知ったきっかけ
今年の夏くらいに見つけたんですが、#flutter
のハッシュタグで誰かのXのポストをたまたま見つけました。
いつか記事にしようと思っててちょうどアドカレ始まったのでこれを題材にしてみる。
DataFlowとは
Pawan Kumarさんが作っている状態管理の仕組み。実態はStreamBuilderのラッパー。
pub.devはこれ
DataFlow is a powerful and flexible state management library for Flutter applications. It provides a simple and intuitive way to manage the flow of data and handle asynchronous operations in your app. With DataFlow, you can easily define actions, track their status, and update your UI accordingly.
DataFlow is designed to be lightweight, efficient, and easy to use. It leverages the power of Dart streams and follows a reactive programming paradigm to ensure smooth data flow and seamless UI updates.
(日本語訳 by deepL)
DataFlowはFlutterアプリケーションのためのパワフルで柔軟な状態管理ライブラリです。データの流れを管理し、アプリの非同期操作を処理するシンプルで直感的な方法を提供します。DataFlowを使えば、アクションを簡単に定義し、そのステータスを追跡し、それに応じてUIを更新することができます。
DataFlowは、軽量で効率的、そして使いやすく設計されています。Dartストリームのパワーを活用し、リアクティブプログラミングパラダイムに従って、スムーズなデータフローとシームレスなUI更新を実現します。
他の状態管理との比較
この比較はDataFlow作者が作ったものなので、実際には自分自身で検証した方がいいと思います。
例えば、GetXはMiddleware SupportがNo
になってますが、Middlewareの仕組みはあります。
DataFlowの仕組み
6種類の機能が提供されている(名前からなんとなく察せる)
- DataAction: Define asynchronous operations as actions with customizable execution logic.
- DataStore: Centralized state management for your application.
- DataChain: You execute one action and based on its result you execute something else.
- DataSync: A widget that rebuilds its descendants based on the state of a DataStore.
- DataSyncNotifier: A widget that notifies listeners when specific DataActions occur.
- Middleware: Intercept and modify actions before and after execution.
カウンターアプリを例に置き換えてみる
どんな感じで使うかカウンターアプリで置き換えてみようと思ったんですが、6種類中カウンターアプリ程度だと3種類で済んでしまったので、どこか時間が取れたらMiddlewareの動きとか紹介できればと。
DataStore
import 'package:dataflow/dataflow.dart';
class CountDataStore extends DataStore {
int count = 0;
}
DataAction
import 'package:dataflow/dataflow.dart';
import 'count_data_store.dart';
class AddCountAction extends DataAction<CountDataStore> {
final int count;
AddCountAction(this.count);
Future<void> execute() async {
store.count += count;
}
}
DataSync
DataSyncのactionsにAddCountActionを追加することによって、AddCountActionがFloatingActionButtonにてキックされた際にDataSyncで検知できて、widgetに状態を通知する
import 'package:dataflow/dataflow.dart';
import 'package:flutter/material.dart';
import 'count_action.dart';
import 'count_data_store.dart';
class CountPage extends StatelessWidget {
const CountPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Flutter x dataflow Demo Page'),
),
body: DataSync<CountDataStore>(
builder: (context, store, hasData) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${store.count}',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
);
},
actions: const {
AddCountAction,
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => AddCountAction(1),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
Discussion