この記事について
provider
開発を主に行なっていたがRiverpod
を使うことになりそうなので学習をしました。
ただグローバルでProvierを定義するため自由度が効きすぎてset/get(購読)
がぱっと見で理解しにくかったため、そこの改善を試みた。
結論
先に結論からいいます。
-
Consumer
で再描画したいWidgetを指定する場合後述するコードは不向き -
override
のアノテーション祭り
実際に開発で利用するかと言われたら多分使わないと思います。
本題
flutter hello wordであるカウンターアプリで作成
環境
[✓] Flutter (Channel beta, 2.11.0-0.1.pre, on macOS 12.3.1 21E258 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.66.2)
[✓] Connected device (2 available)
[✓] HTTP Host Availability
pubspec.yaml
// 追加部分のみ
flutter_riverpod: ^1.0.3
Provider
final countProvider = StateProvider<int>((ref) {
return 0;
});
ViewModel
abstract class HomeInput {
late StateController<int> counterController;
}
abstract class HomeOutput {
late String countString;
}
abstract class HomeViewModeType {
late HomeInput inputs;
late HomeOutput output;
}
class HomeViewModel implements HomeInput, HomeOutput, HomeViewModeType {
HomeViewModel({Key? key, required this.ref}) {
initialize();
}
final WidgetRef ref;
@override
late String countString;
@override
late StateController<int> counterController;
@override
late HomeInput inputs;
@override
late HomeOutput output;
void initialize() {
countString = ref.watch(countProvider).toString();
counterController = ref.watch(countProvider.notifier);
inputs = this;
output = this;
}
}
- input: notifierグループ
- output: stateグループ
- 直接
HomeViewModel
を触れなくするためにTypeを作成(後述)
View
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(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home(title: 'Flutter Demo Home Page'),
);
}
}
class Home extends ConsumerWidget {
Home({Key? key, required this.title}) : super(key: key);
String title = '';
@override
Widget build(BuildContext context, WidgetRef ref) {
final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
homeViewModel.output.countString,
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
homeViewModel.inputs.counterController.update((state) => state + 1);
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
要点
final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);
-> 型をHomeViewModeType
にすることによってinput/outputを経由しないとアクセスできなくしている。
これを今回のタイトルである「制限」と考えてます
まとめ
良かった点
- チーム全体でコードの統一性を確保できる
- 処理の流れの把握がイメージしやすい(個人的に)
- Riverpodの学習になった
悪かった点(重複)
-
Consumer
で再描画したいWidgetを指定する場合後述するコードは不向き -
override
のアノテーション祭り
最後に
ここまで見ていただきありがとうございます!
Riverpodの学習を始めた日の投稿ですので、何か不手際がありましたらアドバイスお待ちしております。
なにかの役に立てれば幸いです!