[読書会]Riverpod.dev/docs 翻訳及び補足(Advanced topics)

Riverpod.dev/docs(開始URL: https://riverpod.dev/docs/introduction/why_riverpod )には日本語訳ページ(/ja)も部分的には既にあるのですが、その部分はそのまま参照して、その他の英語訳のままのページについては自力で翻訳および解説を補足してみました。まだ工事中ですが最終的に満足ができたら上記サイトの翻訳ページに献上できないかな等という目標もあります。

本ブログの(上記Riverpod.dev/docsの)翻訳および解説の目次頁(構成上のトップページ)は次のURLになります。

本頁は、上記のうちの、「Advanced topics」の章の翻訳および解説頁になります。

Advanced topics

注釈)現在Riverpod.dev/docs中の本章「Advanced topics」には既に日本語訳ページ(https://riverpod.dev/ja/docs/advanced/select)が存在しますので、原文はこちらを参照願います。当ブログではこの日本語訳はそのまま参照して補足を追加しています。

パフォーマンスの最適化

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

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

注意)

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

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

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

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

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

Dart
class User {
  late String firstName, lastName;
}

@riverpod
User example(ExampleRef ref) => User()
  ..firstName = 'John'
  ..lastName = 'Doe';

class ConsumerExample extends ConsumerWidget {
  @override
  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)を使用します。
しかし、selectはAsyncValueに適用されるため、待機することはできません。

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

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

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

(次の記事はこちら)

コメントを残す