LoginSignup
0
0

More than 1 year has passed since last update.

[Flutter]Riverpodの扱いが自由すぎるので制限をかけてみた

Posted at

この記事について

provider開発を主に行なっていたがRiverpodを使うことになりそうなので学習をしました。
ただグローバルでProvierを定義するため自由度が効きすぎてset/get(購読)がぱっと見で理解しにくかったため、そこの改善を試みた。

結論

先に結論からいいます。

  • Consumerで再描画したいWidgetを指定する場合後述するコードは不向き
  • overrideのアノテーション祭り

実際に開発で利用するかと言われたら多分使わないと思います。

本題

flutter hello wordであるカウンターアプリで作成

環境

[✓] Flutter (Channel beta, 2.11.0-0.1.pre, on macOS 12.3.1 21E258 darwin-x64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.66.2)
[✓] Connected device (2 available)
[✓] HTTP Host Availability
pubspec.yaml
// 追加部分のみ
flutter_riverpod: ^1.0.3

Provider

final countProvider = StateProvider<int>((ref) {
  return 0;
});

ViewModel

abstract class HomeInput {
  late StateController<int> counterController;
}

abstract class HomeOutput {
  late String countString;
}

abstract class HomeViewModeType {
  late HomeInput inputs;
  late HomeOutput output;
}

class HomeViewModel implements HomeInput, HomeOutput, HomeViewModeType {
  HomeViewModel({Key? key, required this.ref}) {
    initialize();
  }

  final WidgetRef ref;

  @override
  late String countString;

  @override
  late StateController<int> counterController;

  @override
  late HomeInput inputs;

  @override
  late HomeOutput output;

  void initialize() {
    countString = ref.watch(countProvider).toString();
    counterController = ref.watch(countProvider.notifier);
    inputs = this;
    output = this;
  }
}

  • input: notifierグループ
  • output: stateグループ
  • 直接HomeViewModelを触れなくするためにTypeを作成(後述)

View

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(title: 'Flutter Demo Home Page'),
    );
  }
}

class Home extends ConsumerWidget {
  Home({Key? key, required this.title}) : super(key: key);
  String title = '';

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              homeViewModel.output.countString,
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          homeViewModel.inputs.counterController.update((state) => state + 1);
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

要点
final HomeViewModeType homeViewModel = HomeViewModel(ref: ref);

-> 型をHomeViewModeTypeにすることによってinput/outputを経由しないとアクセスできなくしている。

これを今回のタイトルである「制限」と考えてます

まとめ

良かった点

  • チーム全体でコードの統一性を確保できる
  • 処理の流れの把握がイメージしやすい(個人的に)
  • Riverpodの学習になった

悪かった点(重複)

  • Consumerで再描画したいWidgetを指定する場合後述するコードは不向き
  • overrideのアノテーション祭り

最後に

ここまで見ていただきありがとうございます!
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