💟

【Flutter】Riverpod / GetX - カウンターアプリの例による構文比較

5 min read

使用したパッケージ

flutter_riverpod: ^1.0.0-dev.7

get: ^4.3.8

GetXとは

GetXに馴染みがない方はこちらをご参照ください。

https://zenn.dev/inari_sushio/articles/ec573a65df0939
https://zenn.dev/inari_sushio/articles/3ce3494f37166c

main()

Riverpod

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

GetX

GetX
void main() {
  runApp(MyApp());
}

CounterController

カウンター変数、メソッドを保持するクラス。

Riverpod

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

  void increment() {
    state++;
  }
}

// autoDispose適用
final counterProvider = StateNotifierProvider.autoDispose<CounterController, int>(
    (ref) => CounterController());

GetX

GetX
class CounterController extends GetxController {
  var count = 0.obs;

  void increment() {
    count++;
  }
}
// デフォでautoDispose

CounterPage

カウンターの表示、数字の変更をするメインページ。FABからDetailPageに飛べる。リアクティブ。

Riverpod

Riverpod
+ class CounterPage extends ConsumerWidget {
  
+ Widget build(BuildContext context, WidgetRef ref) {
    // 数字が変わると全体が再構築
+   final counter = ref.watch(counterProvider);

    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
+             '$counter',
              style: Theme.of(context).textTheme.headline3,
            ),
            SizedBox(height: 30),
            ElevatedButton(
+             onPressed: ref.read(counterProvider.notifier).increment,
              child: Text('Increment'),
            ),
          ],
        ),
      ),
      // 以下共通
      floatingActionButton: FloatingActionButton(
        onPressed: () => Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => DetailPage(),
          ),
        ),
        child: Icon(Icons.arrow_forward),
      ),
    );
  }
}

GetX

GetX
class CounterPage extends StatelessWidget {
+ final counter = Get.put(CounterController());

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
	    // 数字が変わるとここだけ再構築
+           Obx(() => Text(
+               '${counter.count}',
+               style: Theme.of(context).textTheme.headline3,
+             )),
            SizedBox(height: 30),
            ElevatedButton(
+             onPressed: counter.increment,
              child: Text('Increment'),
            ),
          ],
        ),
      ),
      // 以下共通
      floatingActionButton: FloatingActionButton(
        onPressed: () => Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => DetailPage(),
          ),
        ),
        child: Icon(Icons.arrow_forward),
      ),
    );
  }
}

DetailPage

現在のカウンターの値を取得して表示するページ。非リアクティブ。

Riverpod

Riverpod
class DetailPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Align(
            alignment: Alignment.center,
+           child: Consumer(
+             builder: (context, ref, child) {
+               return Text(
+                 '${ref.read(counterProvider)}',
+                 style: Theme.of(context).textTheme.headline3,
+               );
+             },
+           ),
          ),
	  // 以下共通
          Align(
            alignment: Alignment.topLeft,
            child: IconButton(
              onPressed: () => Navigator.pop(context),
              icon: Icon(Icons.arrow_back),
            ),
          ),
        ],
      ),
    );
  }
}

GetX

GetX
class DetailPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Align(
            alignment: Alignment.center,
+           child: GetBuilder<CounterController>(
+             builder: (controller) {
+               return Text(
+                 '${controller.count}',
+                 style: Theme.of(context).textTheme.headline3,
+               );
+             },
+           ),
          ),
	  // 以下共通
          Align(
            alignment: Alignment.topLeft,
            child: IconButton(
              onPressed: () => Navigator.pop(context),
              icon: Icon(Icons.arrow_back),
            ),
          ),
        ],
      ),
    );
  }
}

Discussion

ログインするとコメントできます