공log/[Flutter]

[Flutter] 플러터 #15 - StateProvider

ming_OoO 2023. 5. 25. 20:31
728x90

상태 관리는 앱 개발에서 중요한 요소 중 하나입니다. Flutter에서는 다양한 상태 관리 패턴과 라이브러리가 제공되는데, 그 중에서도 Riverpod 라이브러리의 StateProvider를 활용하여 효율적으로 상태를 관리할 수 있습니다. 이번 글에서는 StateProvider를 사용하는 예시 코드를 살펴보고, 그 기능과 활용 방법에 대해 알아보겠습니다.

 

먼저 StateProvider의 역할에 대해 알아보겠습니다.

StateProvider의 역할 

  • StateProvider는 Riverpod 라이브러리에서 제공하는 상태 관리 프로바이더 중 하나입니다. 주요 역할은 상태를 저장하고 업데이트하는 것입니다. StateProvider는 값을 제공하고, 해당 값이 변경될 때 위젯을 다시 렌더링하여 UI를 업데이트합니다. 이를 통해 앱의 상태 변화에 따라 UI를 동적으로 조작할 수 있습니다.

 

아래의 코드에서 StateProviderStateStateProvider를 활용하여 상태를 관리하는 코드입니다. 주로 위젯의 상태를 저장하고 업데이트하는 데 사용됩니다.

import 'package:ex_state/layout/default_layout.dart';
import 'package:ex_state/riverpod/state_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class StateProviderScreen extends ConsumerWidget {
  const StateProviderScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final provider = ref.watch(numberProvider);
    // 보통 여기다가 선언함 (build 함수 밑에)
    // 지켜보고 있다가 무언가 변경이 되었을 때 build를 다시 하라는 뜻

    return DefaultLayout(
      title: 'StateProviderScreen',
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              provider.toString(),
            ),
            //
            // StateProvider update 실습
            ElevatedButton(
              onPressed: () {
                ref.read(numberProvider.notifier).update((state) => state + 1);
              },
              child: Text('UPUP'),
            ),
            //
            // StateProvider state 실습
            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'),
            )
          ],
        ),
      ),
    );
  }
}

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: 'StateProviderScreen',
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              provider.toString(),
            ),
            ElevatedButton(
              onPressed: () {
                ref.read(numberProvider.notifier).update((state) => state + 1);
              },
              child: Text('UPUP'),
            ),
          ],
        ),
      ),
    );
  }
}

1. import문

코드의 첫 부분에서는 필요한 패키지를 import하고 있습니다. ex_state/layout/default_layout.dart ex_state/riverpod/state_provider.dart는 사용자 정의 패키지로 추측됩니다. 또한, flutter/material.dart와 flutter_riverpod/flutter_riverpod.dart는 Flutter 및 Riverpod 패키지입니다.

 

2. StateProviderScreen 클래스NextScreen 클래스

StateProviderScreenConsumerWidget을 상속하는 위젯입니다. ConsumerWidget은 상태 변화를 감지하고, 그에 맞춰 위젯을 업데이트하는 기능을 제공합니다.

  • ref.watch(numberProvider) ref.watch 메서드를 사용하여 numberProvider의 상태를 감시합니다. numberProvider는 추후에 정의되는 것으로 보이는 Riverpod 프로바이더입니다.
  • DefaultLayout 위젯 DefaultLayout은 커스텀 위젯으로, 앱의 기본 레이아웃을 구성합니다. title 속성은 'StateProviderScreen'으로 설정되고, body 속성에는 컬럼(Column) 위젯이 포함됩니다.
  • ElevatedButton 위젯 첫 번째 ElevatedButton은 'UPUP'이라는 텍스트를 갖고 있습니다. 버튼을 누르면 ref.read(numberProvider.notifier).update((state) => state + 1) 코드가 실행됩니다. 이는 numberProvider의 상태를 업데이트하는 역할을 합니다.
  • 두 번째 ElevatedButton 두 번째 ElevatedButton은 'Down'이라는 텍스트를 갖고 있습니다. 버튼을 누르면 ref.read(numberProvider.notifier).state = ref.read(numberProvider.notifier).state - 1 코드가 실행됩니다. 이는 numberProvider의 상태를 감소시키는 역할을 합니다.
  • 세 번째 ElevatedButton 세 번째 ElevatedButton은 'Next'라는 텍스트를 갖고 있습니다. 버튼을 누르면 NextScreen으로 이동하는 페이지 전환을 수행합니다.

3. NextScreen 클래스

NextScreen은 또 다른 ConsumerWidget을 상속하는 위젯으로, 이전 화면에서 numberProvider 상태를 감시합니다.

  • build 메서드 build 메서드에서는 numberProvider의 상태를 감시하고, DefaultLayout을 생성합니다. 또한, 'UPUP'이라는 텍스트를 갖는 ElevatedButton을 포함하고 있습니다.

[실행 결과 설명]

- 각각 UPUP과 DOWN을 눌렀을 때

- NEXT로 넘어가서 UPUP을 눌렀을 때

- 뒤로가기를 눌러 이전의 화면으로 돌아갈 때

주어진 코드에서 StateProvider를 사용하여 상태를 관리하고 있습니다. 코드 실행 결과는 다음과 같은 효과를 나타냅니다:

1. StateProviderScreen 실행 결과:

  • 'StateProviderScreen'이라는 제목을 가진 DefaultLayout 위젯이 생성됩니다.
  • 상태 값인 provider를 Text 위젯으로 표시합니다.
  • 'UPUP'이라는 텍스트를 가진 ElevatedButton이 생성됩니다. 이 버튼을 클릭하면 numberProvider의 상태가 1 증가합니다.
  • 'Down'이라는 텍스트를 가진 ElevatedButton이 생성됩니다. 이 버튼을 클릭하면 numberProvider의 상태가 1 감소합니다.
  • 'Next'라는 텍스트를 가진 ElevatedButton이 생성됩니다. 이 버튼을 클릭하면 다음 화면인 NextScreen으로 이동합니다.

2. NextScreen 실행 결과: 

  • 'StateProviderScreen'이라는 제목을 가진 DefaultLayout 위젯이 생성됩니다.
  • 상태 값인 provider를 Text 위젯으로 표시합니다.
  • 'UPUP'이라는 텍스트를 가진 ElevatedButton이 생성됩니다. 이 버튼을 클릭하면 numberProvider의 상태가 1 증가합니다.

따라서, StateProvider를 활용하면 numberProvider라는 상태 변수를 다른 위젯에서 공유하고 업데이트할 수 있습니다. 이로써 상태 변화에 따라 UI가 업데이트되며, 사용자는 버튼을 통해 상태를 증가 또는 감소시킬 수 있습니다. 또한, 다른 화면으로 이동하여 동일한 상태를 공유하고 업데이트할 수도 있습니다.

 

위에서 살펴본 코드는 StateProvider를 사용하여 상태를 관리하는 방법을 보여줍니다. StateProvider는 Riverpod 라이브러리를 기반으로 하며, 앱의 다양한 위젯 간에 상태를 공유하고 업데이트하는 데 사용됩니다. 이를 통해 Flutter 앱의 상태 관리를 보다 쉽고 효율적으로 처리할 수 있습니다.

 

 

728x90