13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

【Flutter】AsyncNotifier で 初期化処理を共通するときは気をつけよう

Posted at

この記事で伝えたいこと

  • state を更新するときは安全に更新できているかしっかり確認しよう

AsyncNotifier.build / Retry 時に全く同じメソッドを使用

もちろん同じメソッドを使用しても問題ない実装もございますが、今回の例ではマズイです。

ホームページ

class HomePage extends ConsumerWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final state = ref.watch(asyncTodosProvider);
    return Scaffold(
      body: state.when(
        data: (data) => ListView.builder(
          itemBuilder: (context, index) => ListTile(
            title: Text(data[index].description),
          ),
          itemCount: data.length,
        ),
        error: (e, s) => Center(
          child: TextButton(
            onPressed: () {
              ref.read(asyncTodosProvider.notifier).fetchTodo();
            },
            child: const Text('Retry'),
          ),
        ),
        loading: () => const CircularProgressIndicator(),
      ),
    );
  }
}

riverpod_generator で実装した AsyncNotifier部分

todo.dart
@riverpod
class AsyncTodos extends _$AsyncTodos {
  Future<List<Todo>> fetchTodo() async {
    final todos = // List<Todo> を取得
    return todos;
  }

  @override
  FutureOr<List<Todo>> build() async {
    return fetchTodo();
  }
}

↑の実装では、エラーをキャッチしてくれない場合があります。その状況と原因はわかりますか?

fetch の再試行時にエラーが発生

AsyncTodos.fetchTodoは内部的に try-catchAsyncValue.guardを使用していないためエラーをキャッチしてくれません。

初期化の fetchTodo と 外部から呼ばれる fetchTodo を分離しよう

外部から呼び出せないプライベートなメソッド: _fetchTodo
外部から呼び出せるため、AsyncValue.guardでエラーハンドリングするメソッド: fetchTodo

todo.dart
@riverpod
class AsyncTodos extends _$AsyncTodos {
  Future<List<Todo>> _fetchTodo() async {
    final todos = // List<Todo> を取得
    return todos;
  }

  @override
  FutureOr<List<Todo>> build() async {
    return _fetchTodo();
  }

  Future<void> fetchTodo() async {
    state = await AsyncValue.guard(_fetchTodo);
  }
}

なぜ_fetchTodoでは、AsyncValue.guardを使用していないのか

実は build 関数内で呼ばれるメソッドは、内部的に AsyncValue.guardで実装されているのです。

安全に AsyncValue を使いこなしましょう!

参考

13
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?