1. 라이브러리 설치



리버팟 라이브러리 설치
flutter_riverpod: ^2.6.1
전용 스니펫 플러그인 설치

해당 플러그인 설치 후 기존 스니펫 작동 안될 경우 위 확인
2. riverpod 코드 작성
창고 만드는 법
파일명은 마지막에 “_vm” 넣기

리버팟 창고 코드
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
// 창고를 업데이트하는 법
- 창고에 사용될 데이터 타입을 작성한다
- 창고 클래스를 생성한다
- Notifier 를 상속 받는다
- 제네릭에 넣을 타입은 사용될 데이터 타입을 넣는다
- 창고 관리자 생성
- 창고 클래스를 리턴하는 익명함수를 넣어 줘야 한다
최상위 위젯을 감싸야 한다
void main() {
// 1. 상태관리 라이브러리 적용
// Adding ProviderScope enables Riverpod for the entire project
runApp(const ProviderScope(child: MyApp()));
}
- 리버팟이 모든 위젯을 관리 할 수 있도록…
창고 구독하는 법

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),
),
),
],
);
}
}

Share article