728x90

Riverpod 라이브러리를 이용한 상태관리 방법에 대해 알아보고 적어둔다.

 

Provider는 상태를 저장하고, 자손 위젯에서 상태에 접근할 수 있도록 제공해주는 InheritedWidget를 래핑한 라이브러리이다. Provider 개발자가 단점을 보완하여 재작성된 라이브러리가 Riverpod 상태 관리 라이브러리이다.

 

1. 먼저 https://pub.dev/packages/riverpod 사이트에서 flutter_riverpod 의 최신버전을 확인하여 pubspec.yaml 에 추가한다.

 

name: riverpod_ex
description: A new Flutter project.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
 
version: 1.0.0+1
 
environment:
  sdk: '>=3.1.5 <4.0.0'
 
dependencies:
  flutter:
    sdk: flutter
 
  cupertino_icons: ^1.0.2
  flutter_riverpod: ^2.4.8
 
dev_dependencies:
  flutter_test:
    sdk: flutter
 
  flutter_lints: ^2.0.0
 
 
flutter:
 
  uses-material-design: true
 

 

 

2. main.dart 파일에서 아래와 같이

_MyApp을 ProviderScope 로 감싸준다.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_ex/screen/home_screen.dart';
 
void main() {
  runApp(ProviderScope(
    child: _MyApp(),
  ));
}
 
class _MyApp extends StatelessWidget {
  const _MyApp({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: HomeScreen(),
    );
  }
}

 

 

3. state_provider.dart

상태관리를 할 StateProvider를 구현한다.

import 'package:flutter_riverpod/flutter_riverpod.dart';
 
final numberProvider = StateProvider<int>((ref) => 0);

 

 

4.state_provider_screen.dart

ConsumerWidget 을 상속하고, Widget build(BuildContext context) 를 Widget build(BuildContext context, WidgetRef ref) 로 변경해준다.

Riverpod에서 정의된 추상클래스 WidgetRef를 통해서 Provider에 접근 가능하고,
ref.watch를 통해서 변경을 감지하면 해당 위젯을 다시 build한다.

 

final provider = ref.watch(numberProvider); 를 추가하여 상태 변화를 감지한다.

Provider의 값이 변경되면 자체적으로 다시 build된다.

 

WidgetRef의 read 메소드를 호출(Provider의 값을 읽어오기만 함)하며, 상태를 변경할 StateProvider의 notifier를 전달한다.

ref.read(numberProvider.notifier).update((state) => state + 1); 로 상태를 증가시키거나,

ref.read(numberProvider.notifier).state = ref.read(numberProvider.notifier).state - 1; 와 같은 방법으로 상태를 감소/증가 시킬 수 있다.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
 
import '../layout/default_layout.dart';
import '../riverpod/state_provider.dart';
 
class StateProviderScreen extends ConsumerWidget {
  const StateProviderScreen({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final provider = ref.watch(numberProvider);
 
    return DefaultLayout(
      title: 'Basic Provider',
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              provider.toString(),
              textAlign: TextAlign.center,
            ),
            ElevatedButton(
              onPressed: () {
                ref.read(numberProvider.notifier).update((state) => state + 1);
              },
              child: Text('UP'),
            ),
            ElevatedButton(
              onPressed: () {
                ref.read(numberProvider.notifier).state =
                    ref.read(numberProvider.notifier).state - 1;
              },
              child: Text(
                'DOWN',
              ),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (_) => _NextScreen()),
                );
              },
              child: Text(
                'Next Screen',
              ),
            ),
          ],
        ),
      ),
    );
  }
}
 
class _NextScreen extends ConsumerWidget {
  const _NextScreen({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final provider = ref.watch(numberProvider);
 
    return DefaultLayout(
      title: 'Basic Provider',
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(
              provider.toString(),
              textAlign: TextAlign.center,
            ),
            ElevatedButton(
              onPressed: () {
                ref.read(numberProvider.notifier).update((state) => state + 1);
              },
              child: Text('UP'),
            ),
          ],
        ),
      ),
    );
  }
}

 

블로그 이미지

Link2Me

,