LoginSignup
0
0

More than 1 year has passed since last update.

Provierを経由してWidgetに値を伝播する方法

Last updated at Posted at 2022-08-31

はじめに

StateNotifierProviderChangeNotifierProvierなどのProviderから、自作のProvierを経由して、Widgetに値を伝播する方法のサンプルです。
メリット等は解説せず、導入後に「実際にどう書けばよいか分からない。。。」と詰まった方向けの内容となっています。

プロバイダからrefを取得する

この章単体で読んでもイメージが掴みにくかったのですが、サンプルコードと一緒だとイメージしやすいと思いサンプルを作りました。
詳細は公式リファレンスをご確認ください。

環境

Flutter: 3.0.5

hooks_riverpod: 1.0.4
flutter_hooks: 0.18.5

結論

以下のコードで下記画面が作れます。
sample.gif

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SamplePage extends HookConsumerWidget {
  const SamplePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      body: Center(
        child: Text(ref.watch(calculatorProvider).calculatedValue.toString()),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: ref.read(numberNotifierProvider.notifier).plusOne,
        child: const Icon(Icons.add),
      ),
    );
  }
}
final calculatorProvider = Provider((ref) => Calculator(ref));

class Calculator {
  Calculator(this.ref);

  final Ref ref;

  int get calculatedValue {
    return ref.watch(numberNotifierProvider) * 2;
  }
}
final numberNotifierProvider =
    StateNotifierProvider<NumberNotifier, int>((ref) => NumberNotifier());

class NumberNotifier extends StateNotifier<int> {
  NumberNotifier() : super(0);

  void plusOne() {
    state++;
  }
}

おまけ①

上記書き方をベースに、Calculatorの部分をViewModelにすることで、MVVMライクなViewModelのProviderを作ることもできます。
※FlutterでMVVMアーキテクチャを推奨している意味合いではございません。本記事ではアーキテクチャについては取り扱いません。

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class SettingPage extends HookConsumerWidget {
  const SettingPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      body: Center(
        child: Text(
          ref.watch(settingPageViewModelProvider).darkMode
              ? 'ダークモード'
              : 'ライトモード',
        ),
      ),
    );
  }
}

final settingPageViewModelProvider =
    Provider((ref) => SettingPageViewModel(ref));

class SettingPageViewModel {
  SettingPageViewModel(this.ref);

  final Ref ref;

  bool get darkMode {
    return ref.watch(darkModeNotifierProvider);
  }
}

final darkModeNotifierProvider =
    StateNotifierProvider<DarkModeNotifier, bool>((ref) => DarkModeNotifier());

class DarkModeNotifier extends StateNotifier<bool> {
  DarkModeNotifier() : super(false);

  void change() {
    state = !state;
  }
}

おまけ②

また、Caluculatorを以下のように書いても上記はじめのコードと全く同じくProviderに値を伝播させることができます。

final calculatorProvider =
    Provider((ref) => Calculator(ref.watch(numberNotifierProvider)));

class Calculator {
  Calculator(this.value);

  final int value;

  int get calculatedValue {
    return value * 2;
  }
}

おわりに

実装に悩んでいる際StateNotifierChangeNotifierを使用して、Widgetに情報を伝える方法を解説している記事は多くヒットしたのですが、Providerを経由した場合の記事がほとんどヒットしなかったので、サンプルコードを記事にしてみました。

この記事で挫折する人を減らしてRiverpodの楽しさを共有できたら幸いです。

// おまけの方が行数多い。。。

0
0
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
0
0