Chuyển đến nội dung chính

レッスン 6: Riverpod を使用した状態管理

プロバイダー対リバーポッド対ブロック。 Riverpod 2.0: プロバイダー、StateProvider、StateNotifierProvider、FutureProvider、StreamProvider。自動破棄、ファミリーモディファイア。コード生成。

💻 プログラミング — レッスン 6 レッスン 6: Riverpod を使用した状態管理

フラッター&ダーツ: 基本から上級まで

パート 2: ナビゲーションと状態管理

xdev.asia

1. リバーポッドのセットアップ

dependencies:
  flutter_riverpod: ^2.5.0
  riverpod_annotation: ^2.3.0

dev_dependencies:
  riverpod_generator: ^2.4.0
  build_runner: ^2.4.0
void main() {
  runApp(const ProviderScope(child: MyApp()));
}

2. プロバイダーの種類

// Simple provider
final greetingProvider = Provider<String>((ref) => 'Hello Riverpod!');

// StateProvider — simple state
final counterProvider = StateProvider<int>((ref) => 0);

// FutureProvider — async data
final productsProvider = FutureProvider<List<Product>>((ref) async {
  final repository = ref.watch(productRepositoryProvider);
  return repository.getAll();
});

// StreamProvider
final messagesProvider = StreamProvider<List<Message>>((ref) {
  return ref.watch(chatServiceProvider).messagesStream;
});

// StateNotifierProvider — complex state
class CartNotifier extends StateNotifier<List<CartItem>> {
  CartNotifier() : super([]);

  void add(Product product) {
    state = [...state, CartItem(product: product, quantity: 1)];
  }

  void remove(String productId) {
    state = state.where((item) => item.product.id != productId).toList();
  }

  double get total => state.fold(0, (sum, item) => sum + item.product.price * item.quantity);
}

final cartProvider = StateNotifierProvider<CartNotifier, List<CartItem>>((ref) {
  return CartNotifier();
});

3. 消費プロバイダー

class ProductListPage extends ConsumerWidget {
  const ProductListPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncProducts = ref.watch(productsProvider);

    return asyncProducts.when(
      data: (products) => ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) => ProductCard(product: products[index]),
      ),
      loading: () => const CircularProgressIndicator(),
      error: (error, stack) => Text('Error: $error'),
    );
  }
}

4.ファミリーと自動廃棄

// Family — parameterized provider
final productByIdProvider = FutureProvider.family<Product, String>((ref, id) async {
  return ref.watch(productRepositoryProvider).getById(id);
});

// AutoDispose — cleanup khi không còn listener
final searchProvider = FutureProvider.autoDispose.family<List<Product>, String>((ref, query) async {
  ref.keepAlive(); // Giữ cache cho đến khi dispose thủ công
  return ref.watch(productRepositoryProvider).search(query);
});

次の記事: ブロックパターンとキュービット。