JINMUSOFTWARE

Riverpod3入門 FutureProvider編

FutureProviderに挑戦してみましょう。

FutureProviderとは?

FutureProviderを使用すると、非同期処理を実行することができます。

jsonファイルを読み込んだり、WebAPIアクセスなどに使用されます。

例えばこんな感じ。async/awaitが使われていますね。

users_provider.dart
final usersProvider = FutureProvider<List<User>>((ref) async {
  final jsonRaw = await rootBundle.loadString('assets/users.json');
  final content = json.decode(jsonRaw) as List<dynamic>;
  return content
      .map((json) => User.fromJson(json as Map<String, dynamic>))
      .toList();
});

環境

  • flutter_riverpod 3.2.0
  • flutter 3.38.6

Install

flutter_riverpodのパッケージをinstallします。

Bash
flutter pub add flutter_riverpod

Version 3.2.0 がインストールされました。

次にlintの設定もしておきましょう。

analysis_options.yaml
plugins:
  riverpod_lint: ^3.1.2

上記だけでいいみたいです。Riverpod 3.2.0 で少し変わったようだ。

lintのversionは最新の番号を指定しましょう。riverpod_lint

flutter_riverpodのバージョンと同じってわけではないようです。

FutureProvider

ではFutureProviderの簡単なコードを書いていきましょう。

FutureProviderは非同期処理を記述することができます。

数秒待機して、日付時刻を返す処理を記述してみます。

ファイル名:time_provider.dart

time_provider.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';

// FutureProviderです。
// async付いていますよ。
final timeProvider = FutureProvider<DateTime>((ref) async {
  await Future.delayed(const Duration(seconds: 1));
  return DateTime.now();
});

次にproviderをwatchして表示する部分を作ります。

main.dartにはいつものimportとProviderScopeを追加します。

main.dart
// import追加
import 'package:flutter_riverpod/flutter_riverpod.dart';

// ProviderScope設置
void main() {
  runApp(const ProviderScope(child: MyApp()));
}

次にConsumerWidgetを継承したWidgetを作成します。

ところで、FutureProviderが提供する値の型は、「AsyncValue<T>」型です。

AsyncValue<T>型には3つの状態があります。

「.when」か「switch式」で切り分けます。

main.dart
// ConsumerWidget継承
class Page1 extends ConsumerWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    //
    // watchします。
    final timeAsyncValue = ref.watch(timeProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('Page 1')),
      body: Center(
        child: Column(
          children: [
            //
            // whenを使用するversion
            timeAsyncValue.when(
              data: (dateTime) => Text('Current Time: $dateTime'),
              loading: () => CircularProgressIndicator(),
              error: (error, stack) => Text('Error: $error'),
            ),

            //
            // switch式
            switch (timeAsyncValue) {
              AsyncData(:final value) => Text('Current Time: $value'),
              AsyncLoading() => const CircularProgressIndicator(),
              AsyncError(:final error) => Text('Error: $error'),
            },
          ],
        ),
      ),
    );
  }
}

実行画面です。日付時刻が表示されましたね。

code
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'time_provider.dart';

void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(colorScheme: .fromSeed(seedColor: Colors.deepPurple)),
      home: const Page1(),
    );
  }
}

class Page1 extends ConsumerWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    //
    final timeAsyncValue = ref.watch(timeProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('FutureProvider Demo')),
      body: Center(
        child: Column(
          children: [
            const SizedBox(height: 20),
            //
            // timeAsyncValueの状態に応じてUIを変える
            // whenを使用するversion
            timeAsyncValue.when(
              data: (dateTime) => Text('Current Time: $dateTime'),
              loading: () => const CircularProgressIndicator(),
              error: (error, stack) => Text('Error: $error'),
            ),
            //
            // Reloadボタン
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                ref.invalidate(timeProvider);
              },
              child: const Text('Reload'),
            ),
            //
          ],
        ),
      ),
    );
  }
}

time_provider.dartはそのまま使えますね。

参考

参考ページ

Riverpod3入門 ProviderとNotifierProvider編

Riverpod3入門 AsyncNotifier編

Riverpod3入門 Generatorコード生成編