0Pricing
Flutter Mobile Development · 강의

상태 관리를 위한 Riverpod

견고하고 테스트 가능한 상태 관리 라이브러리인 Riverpod을 살펴보고, 복잡한 앱에서 다른 솔루션보다 나은 장점을 이해합니다.

상태 관리를 위한 Riverpod은(는) CoddyKit의 무료 Flutter Mobile Development 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Flutter Mobile Development 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Flutter Mobile Development 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Welcome to Riverpod!

Riverpod is a popular state management library for Flutter that aims to be simple, robust, and testable. It's a reimagined version of the Provider package, designed to address some of its limitations.

Think of Riverpod as a powerful toolkit for managing all the data in your app, from user settings to fetched data, in a safe and predictable way.

Riverpod's Core Strengths

Riverpod offers several key advantages:

  • Compile-time Safety: Catches errors early, before your app even runs.
  • Testability: Makes it easy to test your business logic in isolation.
  • Auto-Dispose: Providers can automatically clean up resources when no longer needed.
  • No Widget Tree Dependency: Providers don't rely on the widget tree, making them more flexible.

It helps you write cleaner, more maintainable code.

Setting Up Your App

To use Riverpod, first add the flutter_riverpod package to your pubspec.yaml. Then, wrap your entire application with a ProviderScope widget. This widget stores the state of all your providers.

Here's how to set it up:

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

void main() {
  runApp(
    // Wrap your app in a ProviderScope
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Text('Hello Riverpod'),
    );
  }
}

Introducing Providers

Providers are the core building blocks of Riverpod. They hold a piece of state and allow you to access it from anywhere in your app.

The simplest provider is a Provider, which holds an immutable value. You define it globally, making it accessible throughout your application.

import 'package:flutter_riverpod/flutter_riverpod.dart';

// A simple Provider that holds an immutable string.
final greetingProvider = Provider<String>((ref) {
  return 'Hello from Riverpod!';
});

// You can also provide numbers, objects, etc.
final counterProvider = Provider<int>((ref) => 0);

Consuming Providers with `ConsumerWidget`

To read a provider's value in your UI, you use a ConsumerWidget. This widget gives you access to a WidgetRef (often named ref), which lets you 'watch' or 'read' providers.

ref.watch() makes your widget rebuild when the provider's value changes.

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

final greetingProvider = Provider<String>((ref) {
  return 'Hello Riverpod User!';
});

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ConsumerWidget(
        builder: (context, ref, child) {
          final greeting = ref.watch(greetingProvider);
          return Scaffold(
            appBar: AppBar(title: Text('Riverpod App')),
            body: Center(child: Text(greeting)),
          );
        },
      ),
    );
  }
}

Mutable State with `StateProvider`

When you need to change a piece of state directly, use a StateProvider. It exposes a StateController, which has a state property you can modify.

This is perfect for simple UI states like a toggle or a counter.

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

// A StateProvider for a simple counter.
final counterProvider = StateProvider<int>((ref) => 0);

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ConsumerWidget(
        builder: (context, ref, child) {
          final count = ref.watch(counterProvider);
          return Scaffold(
            appBar: AppBar(title: Text('Counter App')),
            body: Center(
              child: Text(
                'Count: $count',
                style: TextStyle(fontSize: 24),
              ),
            ),
            floatingActionButton: FloatingActionButton(
              onPressed: () => ref.read(counterProvider.notifier).state++,
              child: Icon(Icons.add),
            ),
          );
        },
      ),
    );
  }
}

`StateNotifierProvider` for Logic

For more complex state that involves business logic (e.g., fetching data, managing lists), you'll use a StateNotifier with StateNotifierProvider.

StateNotifier is a class you extend, and it holds your state. The provider then exposes an instance of your notifier.

import 'package:flutter_riverpod/flutter_riverpod.dart';

// 1. Define your state class (immutable recommended)
class Todo { 
  final String id; 
  final String description; 
  final bool completed; 
  Todo(this.id, this.description, this.completed); 
}

// 2. Create a StateNotifier to manage the state
class TodosNotifier extends StateNotifier<List<Todo>> {
  TodosNotifier() : super([]); // Initial state is an empty list

  void addTodo(String description) {
    state = [...state, Todo(DateTime.now().toString(), description, false)];
  }

  void toggle(String id) {
    state = [ 
      for (final todo in state) 
        if (todo.id == id) 
          Todo(todo.id, todo.description, !todo.completed) 
        else 
          todo, 
    ];
  }
}

// 3. Create the StateNotifierProvider
final todosProvider = StateNotifierProvider<TodosNotifier, List<Todo>>((ref) {
  return TodosNotifier();
});

Async Data with `FutureProvider`

Riverpod makes handling asynchronous data (like network requests) a breeze with FutureProvider and StreamProvider.

A FutureProvider exposes an AsyncValue, which gracefully handles loading, error, and data states in your UI.

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

// A FutureProvider that simulates fetching data.
final userProvider = FutureProvider<String>((ref) async {
  await Future.delayed(Duration(seconds: 2)); // Simulate network delay
  return 'John Doe';
});

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ConsumerWidget(
        builder: (context, ref, child) {
          final userAsyncValue = ref.watch(userProvider);
          return Scaffold(
            appBar: AppBar(title: Text('Async Data')),
            body: Center(
              child: userAsyncValue.when(
                loading: () => CircularProgressIndicator(),
                error: (err, stack) => Text('Error: $err'),
                data: (user) => Text('User: $user', style: TextStyle(fontSize: 24)),
              ),
            ),
          );
        },
      ),
    );
  }
}

`ref.read` vs `ref.watch`

When interacting with providers, you'll primarily use two methods on the ref object:

  • ref.watch(provider): Listens to changes in a provider. If the provider's state changes, the widget or provider watching it will rebuild/re-execute. Use this in build methods.
  • ref.read(provider): Reads a provider's current value once, without listening for future changes. Ideal for one-off actions, like button presses or initial setup.

Avoid ref.read in build methods unless you specifically don't want rebuilds.

Riverpod Provider Types

Which Riverpod provider types are best suited for managing a simple counter (a single integer that can be incremented/decremented) and for handling complex business logic with multiple actions (e.g., adding/removing items from a to-do list)?

Riverpod Recap

Great job! You've explored Riverpod, a powerful and modern state management solution for Flutter.

  • We learned about ProviderScope for app setup.
  • We used Provider for immutable data and StateProvider for simple mutable state.
  • For complex logic, StateNotifierProvider with StateNotifier is key.
  • FutureProvider helps manage async data gracefully.
  • Remember ref.watch for listening and ref.read for one-time access.

Riverpod's compile-time safety and testability make it an excellent choice for robust Flutter applications!

자주 묻는 질문

“상태 관리를 위한 Riverpod” 강의는 무료인가요?

네 — “상태 관리를 위한 Riverpod” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Flutter Mobile Development 강의 전체를 잠금 해제할 수 있습니다. Flutter Mobile Development 강의에는 총 4개의 강의가 포함되어 있습니다.

“상태 관리를 위한 Riverpod”에서 뭘 배우나요?

견고하고 테스트 가능한 상태 관리 라이브러리인 Riverpod을 살펴보고, 복잡한 앱에서 다른 솔루션보다 나은 장점을 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Flutter Mobile Development을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Flutter Mobile Development을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Flutter Mobile Development은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“상태 관리를 위한 Riverpod” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Flutter Mobile Development 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Flutter Mobile Development 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. setState 및 InheritedWidget
  2. Provider 패키지 기초
  3. 상태 관리를 위한 Riverpod
  4. Stream을 활용한 BLoC 패턴
← Flutter Mobile Development(으)로 돌아가기