개발/Android

[Flutter] Riverpod 상태관리 - ConsumerStatefulWidget 가이드

y_lime 2025. 4. 2. 14:13

✅ ConsumerStatefulWidget을 사용해야 하는 경우

ConsumerStatefulWidget은 setState()와 Riverpod 상태 관리를 동시에 사용해야 할 때 필요하다.

예를 들어, 사용자가 버튼을 클릭할 때마다 UI가 변경되지만, 추가적인 상태(예: 애니메이션 컨트롤러, 텍스트 필드 입력 등)도 관리해야 할 경우 ConsumerStatefulWidget을 사용하면 적절하다.


🛠 ConsumerStatefulWidget 예제 코드 (텍스트 필드 + 상태 관리)

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

/// 상태 관리 (카운터)
class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

final counterProvider = StateNotifierProvider<CounterNotifier, int>(
  (ref) => CounterNotifier(),
);

class CounterScreen extends ConsumerStatefulWidget {
  @override
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends ConsumerState<CounterScreen> {
  String userInput = "";

  @override
  Widget build(BuildContext context) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: const Text('ConsumerStatefulWidget Example')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Count: $count',
              style: const TextStyle(fontSize: 24),
            ),
            const SizedBox(height: 20),
            TextField(
              onChanged: (value) {
                setState(() {
                  userInput = value;
                });
              },
              decoration: InputDecoration(
                labelText: "Enter something",
                border: OutlineInputBorder(),
              ),
            ),
            const SizedBox(height: 20),
            Text("User Input: $userInput"),
            const SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                IconButton(
                  onPressed: () => ref.read(counterProvider.notifier).decrement(),
                  icon: const Icon(Icons.remove),
                ),
                IconButton(
                  onPressed: () => ref.read(counterProvider.notifier).increment(),
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

왜 ConsumerStatefulWidget을 사용해야 할까?

  1. TextField 입력값을 유지해야 하므로 setState()가 필요
  2. 동시에 Riverpod 상태(counterProvider)도 관리해야 한다.
  3. ConsumerWidget으로는 setState()를 사용할 수 없기 때문에 ConsumerStatefulWidget이 적절한 선택이다.

결론

- ConsumerStatefulWidget은 setState()가 필요한 상황에서 Riverpod을 함께 사용할 때 필요
- 일반적으로 상태 관리만 필요하면 ConsumerWidget을 사용하고, setState()가 필요할 경우 ConsumerStatefulWidget을 사용하면 된다 !