App/Flutter

[ FLUTTER ] Riverpod 카운트증가 앱 예제

거북 2023. 8. 17. 09:50
// ignore_for_file: prefer_const_constructors
// 58:26 (https://www.youtube.com/watch?v=vtGCteFYs4M)

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

void main() {
  // riverpod을 사용하기 위해 ProviderScope로 뚜껑을 감싸줌
  runApp(ProviderScope(child: const App()));
}

// null값 계산을 위한 +연산자오버로딩
extension OptionalInfixAddition<T extends num> on T? {
  T? operator +(T? other) {
    final shadow = this;
    if (shadow != null) {
      return shadow + (other ?? 0) as T;
    } else {
      return null;
    }
  }
}

// getx와 같은 상태를 관리할 함수저장소
class Counter extends StateNotifier<int?> {
  Counter() : super(null);
  // 연산자오버로딩 처리를 하였기 때문에 null값에 대한 오류가 발생하지 않음.
  void increment() => state = state == null ? 1 : state + 1;
  // void increment() => state++;
  int? get value => state;
}

// 프로바이더변수
final counterProvider = StateNotifierProvider<Counter, int?>(
  (ref) => Counter(),
);

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      darkTheme: ThemeData.dark(),
      themeMode: ThemeMode.dark,
      debugShowCheckedModeBanner: false,
      home: const HomePage(),
    );
  }
}

// 구독위젯이 들어갈 컨슈머위젯
class HomePage extends ConsumerWidget {
  const HomePage({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      // appBar: AppBar(title: Text('Hooks Riverpod')),
      appBar: AppBar(
        // obx와 같은 구독 위젯
        title: Consumer(
          builder: (context, ref, child) {
            final count = ref.watch(counterProvider);
            final text = count == null ? 'Press the button' : count.toString();
            return Text(text);
          },
        ),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          TextButton(
            onPressed: () {
              ref.read(counterProvider.notifier).increment();
            },
            child: const Text('Increment counter'),
          ),
        ],
      ),
    );
  }
}