メインコンテンツに進む

パフォーマンスの最適化

これまで見てきた内容で、すでに完全に機能するアプリケーションを構築できます。
しかし、読み込みのパフォーマンスについて疑問があるかもしれません。

このページでは、コードを最適化するためのいくつかのヒントとコツを紹介します。

注意

最適化を行う前にアプリケーションのベンチマークを行ってください。
最適化による複雑さの増加は、わずかな性能向上には見合わないかもしれません。

"select"を使ったウィジェット/provider の再ビルドのフィルタリング

デフォルトでは、ref.watchを使用すると、オブジェクトのプロパティのいずれかが変更されるたびに、consumer/provider が再ビルドされることに気づいたかもしれません。
例えば、Userを監視して"name"のみを使用している場合でも、"age"が変更されると consumer は引き続き再ビルドされます。

しかし、consumer が一部のプロパティのみを使用している場合、他のプロパティが変更された場合のウィジェットの再ビルドは避けたいでしょう。

これは provider のselect機能を使用することで実現できます。 これを行うと、ref.watchは全体のオブジェクトではなく、選択されたプロパティのみを返します。
そして、consumer/provider は選択されたプロパティが変更された場合にのみ再ビルドされるようになります。

class User {
late String firstName, lastName;
}


User example(Ref ref) => User()
..firstName = 'John'
..lastName = 'Doe';

class ConsumerExample extends ConsumerWidget {

Widget build(BuildContext context, WidgetRef ref) {
// 次のように書く代わりに:
// String name = ref.watch(provider).firstName!;
// 以下のように書くことができます:
String name = ref.watch(exampleProvider.select((it) => it.firstName));
// これにより、このウィジェットは'firstName'の変更のみを監視するようになります。

return Text('Hello $name');
}
}
備考

selectを何度でも呼び出すことができます。
必要なプロパティごとに一度呼び出すことができます。

注意

選択されたプロパティは不変であることが期待されます。
Listを返してそのリストを変更しても、再ビルドはトリガーされません。

注意

selectを使用すると、個々の読み取り操作がわずかに遅くなり、コードの複雑さがわずかに増します。
"他のプロパティ"がほとんど変更されない場合は、使用する価値がないかもしれません。

非同期プロパティの選択

別の provider を監視している provider を最適化しようとしている場合、その別の provider が非同期である可能性があります。

通常は、値を取得するために ref.watch(anotherProvider.future)を使用します。
しかし、selectAsyncValueに適用されるため、待機することはできません。

この目的のために、selectAsyncを代わりに使用できます。
これは非同期コードに特有で、provider から発信されたデータに対して select 操作を実行できます。
その使用法はselectと似ていますが、代わりにFutureを返します:


Object? example(Ref ref) async {
// ユーザーが利用可能になるのを待ち、"firstName"プロパティのみを監視する
final firstName = await ref.watch(
userProvider.selectAsync((it) => it.firstName),
);

// TODO "firstName"を使用して他のものを取得する
}