この記事は ウェブクルー Advent Calendar 2022 22日目の記事です。
昨日は @tatsuyanamiki さんの「PageSpeed Insightsで指摘されがちな改善提案と対策について」でした。
はじめに
ウェブクルーでは、今年度よりアプリ開発準備室という、モバイルアプリ開発のスキル向上や、
モバイルアプリ開発組織の拡大に向けたナレッジ構築、企画開発をしていくチームを発足しました。
その中で採用した技術の1つに、モバイルアプリフレームワークの Flutter があります。
今回は、そのFlutterアプリ開発のスキル向上の際に培った技術の中で、
Riverpodの機能を活用した画面遷移で試した方法を記事にまとめようと思います。
なお、Flutter環境構築やRiverpodについての説明は割愛します。
ページ間で引数を渡す
Flutterの画面遷移で調べていて、よく見かけた引数を渡す実装は、
下記の実装例のようにページ間で引数を渡していることが多かったです。
文字列 testId
を画面遷移時に渡す場合:
画面遷移先では testId
を受け取り、
受け取った testId
を使ってViewModelなどに用意した関数を実行します。
class TestPage extends HookConsumerWidget {
final String testId;
const TestPage({Key? key, required this.testId}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(testViewModelProvider);
final testViewModel = ref.watch(testViewModelProvider.notifier);
useEffect(() {
Future(() {
testViewModel.fetchByTestId(testId);
});
return null;
}, []);
// ~~~ 省略 ~~~
}
}
画面遷移元では、onTap
や onPressed
の処理で引数 testId
を渡しています。
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return TestPage(testId: data.testId);
},
),
);
ProviderScope override
上記の実装例だと、画面遷移元から渡された testId
を
画面遷移先のMVVMでいうViewから引き回して操作するような実装になっています。
引数の数が増えたり呼び出す関数が増えると、View内の実装や定義も煩雑になってきます。
そこで、 ProviderScope
の override
を活用した実装です。
ProviderScope
の override
を活用すると、
ページ間で引数を渡すことなく、 Provider
を上書きして引数を設定することができます。
Provider.family
ProviderScope
の override
を活用する上で、
Provider.family
についても知っておく必要があります。
Provider.family
修飾子を付けて Provider
を作成すると、
Provider
に引数を設定することができるようになります。
この Provider.family
を override
することで、
ページ間で引数を渡すことなく、 Provider
に引数を渡すことができます。
実装例
Provider
と Provider.family
を用意します。
実装例ではMVVMでいうViewModelにあたる部分に実装しています。
final testViewModelProviderFamily =
StateNotifierProvider.autoDispose.family<TestViewModel, AsyncValue<TestState>, String>(
(ref, testId) => TestViewModel(testId, ref: ref));
final testViewModelProvider =
StateNotifierProvider.autoDispose<TestViewModel, AsyncValue<TestState>>(
(ref) => throw UnimplementedError());
class TestViewModel extends StateNotifier<AsyncValue<TestState>> {
final AutoDisposeStateNotifierProviderRef _ref;
final String testId;
TestViewModel(this.testId, {required AutoDisposeStateNotifierProviderRef ref})
: _ref = ref,
super(const AsyncLoading());
// ~~~ 省略 ~~~
}
画面遷移元の onTap
や onPressed
の処理で Provider.family
を override
します。
この際、ページ間で引数を渡す必要はないので、 child: const TestPage()
となります。
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ProviderScope(
overrides: [
testViewModelProvider
.overrideWithProvider(testViewModelProviderFamily(data.testId))
],
child: const TestPage()
)
)
)
画面遷移後は下記のように参照できます。
画面遷移前の ProviderScope
の override
で引数 testId
を渡しているので、
画面遷移後のページ側では引数を意識することなく記述ができます。
class TestPage extends HookConsumerWidget {
const TestPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(testViewModelProvider);
final testViewModel = ref.watch(testViewModelProvider.notifier);
useEffect(() {
Future(() {
testViewModel.fetchByTestId();
});
return null;
}, []);
// ~~~ 省略 ~~~
}
}
おわりに
ProviderScope
の override
を活用することで、
画面遷移時に引数を引き回すことなく、実装する方法について簡単にまとめました。
Provider.family
の引数には、文字列以外にも独自に実装したクラスも渡せるので、
複数の引数を1つのクラスにまとめて設定することも可能です。
現在のアプリ開発準備室は、Flutterを活用した複数のアプリの企画開発と並行して、
実際にリリースしたモバイルアプリの運用フェーズに進みつつあります。
モバイルアプリ開発に限らず、企画で挙がった内容に併せて、Web版やAPIの開発も進めていきます。
明日は、 @ee4839 さんです。
よろしくお願いします。
ウェブクルーでは一緒に働いていただける方を随時募集しております。
お気軽にエントリーくださいませ。
https://www.webcrew.co.jp/recruit/