【Flutter】共通で使えるLoadingのProviderを作ってみた

![スクリーンショット 2023-12-14 10.08.23（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/63604b7b-a9ba-473c-6ebd-ddb5f9f22eac.png)


<a href="https://qiita.com/advent-calendar/2023/yumemi-23-graduation">
  <img alt="YUMEMI New Grad Advent Calendar 2023" width="1240" height="112" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/6d8a7098-9aef-a19a-54fe-83a2d493e033.png">
</a>

:::note info
この記事は、<b>株式会社ゆめみの23卒 Advent Calendar 2023</b>のアドベントカレンダーになります！！
色々な種類の記事が投稿されるので、お楽しみに🤗
:::

https://qiita.com/advent-calendar/2023/yumemi-23-graduation

# はじめに
今回は、共通で使えるLoadingのProviderを作ってみたのでその記事を書いていこうと思います。
意外と共通で使えるので便利だなと思ったりました。


# 今回使用するPackage
- 不足していたりしましたら、教えていただけると幸いです🙇

```yaml:pubspec.yaml
dependencies:
  flutter_riverpod: ^2.4.5
  riverpod_annotation: ^2.3.0

dev_dependencies:
  build_runner: ^2.4.6
  riverpod_generator: ^2.3.5
  riverpod_lint: ^2.3.3
```

# 共通で使えるLoadingのProviderを作成してみる

```dart
part 'loading.g.dart';

@riverpod
class Loading extends _$Loading {
  @override
  bool build() => false;

  bool isLoading({required bool value}) {
    return state = value;
  }
}
```

では実際に、ViewModel・State・Viewの中での使用例を記載していきます。

```dart: home_page_state.dart
part 'home_page_state.freezed.dart';

@freezed
class HomePageState with _$HomePageState {
  const factory HomePageState({
    @Default(0) int counter,
  }) = _HomePageState;
}
```

```dart:home_page_view_model.dart
part 'home_page_view_model.g.dart';

@riverpod
class HomePageViewModel extends _$HomePageViewModel {
  @override
  HomePageState build({
    HomePageState initState = const HomePageState(),
  }) {
    return initState;
  }

  Loading get loading => ref.read(loadingProvider.notifier);

  Future<void> onTap() async {
    loading.state = true;
    // わかりやすくするためにに遅延をかける
    await Future.delayed(Duration(seconds: 3));
    state = state.copyWith(
      counter: state.counter + 1,
    );
    loading.state = false;
  }
}
```

```dart:home_page.dart
class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final loading = ref.watch(loadingProvider);
    final state = ref.watch(homePageViewModelProvider());
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppAppBar(),
      body: Stack(
        children: [
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                SizedBox(height: 50),
                Text('${state.counter}'),
              ],
            ),
          ),
          if (loading)
            Center(
              child: CircularProgressIndicator(),
            )
          else
            SizedBox(),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: ref.read(homePageViewModelProvider().notifier).onTap,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
```

実装してみた時のUIをこちらに載せます！！


![Simulator Screen Recording - iPhone 15 Pro - 2023-12-14 at 10.36.52.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/7f085120-cdee-0daf-5a4a-4a41168747e9.gif)

# 最後に

UIはあまり良くありませんが、何かに使う場合に役立てればいいなと思います。


# ちょっとした宣伝

株式会社ゆめみの23卒のメンバーでアドベントカレンダーを作成しています。
新卒のフレッシュな記事がたくさん投稿予定なので、少しでも興味があれば購読いただけると幸いです！！


https://qiita.com/advent-calendar/2023/yumemi-23-graduation



<a href="https://qiita.com/advent-calendar/2023/yumemi-23-graduation">
  <img alt="YUMEMI New Grad Advent Calendar 2023" width="1240" height="112" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/6d8a7098-9aef-a19a-54fe-83a2d493e033.png">
</a>