inblog logo
|
jjack1
    Flutter

    [Flutter] flutter_riverpod 상태 관리 라이브러리

    만들면서 배우는 플러터 앱 프로그래밍
    최재원's avatar
    최재원
    Jul 30, 2025
    [Flutter] flutter_riverpod 상태 관리 라이브러리
    Contents
    1. 라이브러리 설치전용 스니펫 플러그인 설치2. riverpod 코드 작성창고 만드는 법최상위 위젯을 감싸야 한다창고 구독하는 법창고 업데이트 하는 법riverpod으로 유저 객체 다루기

    프로젝트 코드

    https://github.com/flutter-lec/riverpod_sample

    1. 라이브러리 설치

    notion image
    notion image
    notion image

    리버팟 라이브러리 설치

    flutter_riverpod: ^2.6.1

    전용 스니펫 플러그인 설치

    notion image
    커스텀 코드 스니펫 설정
    해당 플러그인 설치 후 기존 스니펫 작동 안될 경우 위 확인

    2. riverpod 코드 작성

    창고 만드는 법

    파일명은 마지막에 “_vm” 넣기

    notion image

    리버팟 창고 코드

    import 'package:flutter_riverpod/flutter_riverpod.dart'; // 1. 창고 데이터 타입(int 면 안 만들어도 됨) // 관리 타입은 1가지만 가능함 여러개면 클래스 타입 안에 넣어서 사용함 // 2. 창고 // <> <- 내부에는 관리하고 싶은 type 을 작성하면 됨 class HomeVM extends Notifier<int> { // 창고가 만들어질 때 초기화 메서드(return 하는 값을 창고가 state 로 관리함) @override int build() { print("창고 빌드 후 상태 초기화"); return 1; } void increase() { state++; // setState 가 필요하지 않음. state 가 변화 되면 알아서 알려줌 } } // 3. 창고 관리자 <창고이름, 관리타입> final homeProvider = NotifierProvider<HomeVM, int>(() { print("창고 생성"); return HomeVM(); }); // 창고 만드는 법 // 창고 구독하는 법 - read or watch // 창고를 업데이트하는 법
    1. 창고에 사용될 데이터 타입을 작성한다
    1. 창고 클래스를 생성한다
      1. Notifier 를 상속 받는다
      2. 제네릭에 넣을 타입은 사용될 데이터 타입을 넣는다
    1. 창고 관리자 생성
      1. 창고 클래스를 리턴하는 익명함수를 넣어 줘야 한다

    최상위 위젯을 감싸야 한다

    void main() { // 1. 상태관리 라이브러리 적용 // Adding ProviderScope enables Riverpod for the entire project runApp(const ProviderScope(child: MyApp())); }
    • 리버팟이 모든 위젯을 관리 할 수 있도록…

    창고 구독하는 법

    notion image

    read

    watch

    • state가 변화하면 model 변수에 변화된 state 값을 계속 받는다
    • 구독하고 있는 state 가 변화하면 rebuild 한다
    class HeaderPage extends ConsumerWidget { HeaderPage(); @override Widget build(BuildContext context, WidgetRef ref) { // 모든 provider에게 접근할 수 있는 변수 ref print("header 빌드"); // state를 받는 변수를 model로 사용함 // 이 watch 하면 창고가 만들어짐 print("창고 생성전"); int model = ref.watch(homeProvider); // watch 를 사용하면 창고의 state에 바로 접근한다. return yield 방법으로 한다. print("창고 생성후"); return Container( color: Colors.red, child: Align( child: Text( "$model", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100, decoration: TextDecoration.none, ), ), ), ); } }
     

    창고 업데이트 하는 법

    • 창고 관리자를 통해 창고를 1번 읽는다
    • 해당 창고에 있는 함수를 실행 한다
    • 함수가 실행되면서 state 가 변한다
    class BottomPage extends ConsumerWidget { BottomPage(); @override Widget build(BuildContext context, WidgetRef ref) { print("bottom 빌드"); // 창고에 접근하는 법 // 창고 타입을 받아야함. 이름은 vm 을 사용 HomeVM vm = ref.read(homeProvider.notifier); return Container( color: Colors.blue, child: Align( child: ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: () { print("버튼 클릭됨"); vm.increase(); }, child: Text( "증가", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 100), ), ), ), ); } }
     

    riverpod으로 유저 객체 다루기

    리버팟 창고

    import 'package:flutter_riverpod/flutter_riverpod.dart'; // 1. 창고 데이터 타입(int 면 안 만들어도 됨) // 관리 타입은 1가지만 가능함 여러개면 클래스 타입 안에 넣어서 사용함 class User { String name; int age; User(this.name, this.age); } // 2. 창고 // <> <- 내부에는 관리하고 싶은 type 을 작성하면 됨 class HomeVM extends Notifier<User> { // 창고가 만들어질 때 초기화 메서드(return 하는 값을 창고가 state 로 관리함) @override User build() { print("창고 빌드 후 상태 초기화"); return User("", 0); } void changeUser({required String name, required int age}) { state = User(name, age); // state에는 항상 새로운 객체를 넣어야함. 기존 객체 수정 ❌ // setState 가 필요하지 않음. state 가 변화 되면 알아서 알려줌 } } // 3. 창고 관리자 <창고이름, 관리타입> final homeProvider = NotifierProvider<HomeVM, User>(() { print("창고 생성"); return HomeVM(); });

    입력 창

    import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:riverpod_test/home_vm.dart'; void main() { runApp(const ProviderScope(child: MyApp())); } class MyApp extends StatelessWidget { const MyApp(); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: HomePage(), ); } } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: ListView( children: [ Header(), Bottom(), ], ), ); } } class Bottom extends ConsumerWidget { TextEditingController _name = TextEditingController(); TextEditingController _age = TextEditingController(); void submit(vm) { print(_name.text); print(_age.text); // 상태를 바꿔야함 vm.changeUser(name: _name.text, age: int.parse(_age.text)); } @override Widget build(BuildContext context, WidgetRef ref) { HomeVM vm = ref.read(homeProvider.notifier); return Form( child: Column( children: [ TextField( decoration: InputDecoration(hintText: "이름입력"), controller: _name, ), TextField( decoration: InputDecoration(hintText: "나이입력"), controller: _age, ), TextButton(onPressed: () => submit(vm), child: Text("입력")), ], ), ); } } class Header extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { User model = ref.watch(homeProvider); return Column( children: [ Container( child: Text( "이름 : ${model.name}", style: TextStyle(fontSize: 40), ), ), Container( child: Text( "나이 : ${model.age}", style: TextStyle(fontSize: 40), ), ), ], ); } }
    notion image
    출처: 만들면서 배우는 플러터 앱 프로그래밍
     
    Share article
    Contents
    1. 라이브러리 설치전용 스니펫 플러그인 설치2. riverpod 코드 작성창고 만드는 법최상위 위젯을 감싸야 한다창고 구독하는 법창고 업데이트 하는 법riverpod으로 유저 객체 다루기

    jjack1

    RSS·Powered by Inblog