stateNotifier는 changeNotifier의 업그레이드 버전이라고 볼 수 있다.
그럼 먼저 changeNotifier에 대해 알아보자..
▶ ChangeNotifier 란?
변경사항을 알리고 싶을 때마다 리스너에게 알림을 제공하는 클래스
- notifyListeners() 클래스에 변화가 있을 때 해당 메서드를 호출할 수 있다.
- ValueNotifier는 단일 값만을 전달하는 ChangeNotifier의 일종이다(오직 하나의 변경된 값만을 전달할 수 있다.)
class MyValueNotifier extends ValueNotifier<int>{
//하나의 값만을 갖고 있을 수 있음
int getValue() => value;
}
class MyChangeNotifier extends ChangeNotifier{
// multiple한 값들 가능
}
이 두가지를 사용했을 때의 몇가지 문제점이 존재한다..
1. ChangeNotifier와 ValueNotifier는 mutable 이라 클래스 외부 누구나 notifier의 상태를 변경 가능하다.
→ 이는 원하지 않은 상호작용을 야기할 수 있다.
2. ChangeNotifier를 사용하는 동안에는 notifyListeners()를 일일이 호출해야 한다.
class ItemNotifier extends ChangeNotifier {
final List<String> _items = <String>[];
int _size = 0;
...
void add(String value) {
_items.add(value);
_size++;
notifyListeners();
}
}
이러한 단점들을 보완한 것이 StateNotifier이다
▶ StateNotifier의 장점
- 본질적으로 immutable한 속성임
- 이전상태과 새로운 상태를 비교하며 이를 리스너에게 자동으로 알림
- 단일 데이터의 수정 point 이다
StateNotifier가 무엇인지 알았으니 이제 사용해보자..
먼저, pubspec.yaml 파일에 아래 두개의 dependency를 추가하자
// # pubspec.yaml
dependencies:
state_notifier:
flutter_state_notifier:
간단한 counter 클래스를 가지고 StateNotifier를 활용해볼 예정이다.
riverpod 패키지를 import 해 주고, StateNotifier 옆에 전달하고자 하는 변수의 형을 넣어준다
그 다음 그 밑에, StateCounter 인스턴스를 global 하게 선언해준다
counter.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
class StateCounter extends StateNotifier<int> {
StateCounter() : super(0);
void increment() {
state++;
}
void decrement() {
state--;
}
}
final StateCounter myCounter = StateCounter();
이제 StateNotifierBuilder를 사용해서 바뀐 값을 위젯에 적용하는 방법을 알아보겠다.
먼저 버튼 클릭을 통해 값을 증가해 줄테니, onpressed에 myCounter를 증가해보자..
floatingActionButton: FloatingActionButton(
onPressed: () => myCounter.increment(),
...
),
다음으로는 변경하고자 하는 위젯을 StateNotifierBuilder로 감싸고
builder를 통해 값을 전달한다..
body: StateNotifierBuilder(
stateNotifier: myCounter,
builder: (context, value, child) {
return Center(
child: Text(value.toString()),
);
},
),
최종 코드
import 'package:flutter/material.dart';
import 'package:flutter_state_notifier/flutter_state_notifier.dart';
...
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
...
floatingActionButton: FloatingActionButton(
// 1.
onPressed: () => myCounter.increment(),
child: const Icon(Icons.add),
),
body: StateNotifierBuilder(
stateNotifier: myCounter,
builder: (context, value, child) {
// 2.
return Center(
child: Text(value.toString()),
);
},
),
);
}
}
riverpod를 사용할 때, 물론 ChangeNotifier와 ValueNotifier를 사용할 수 있지만
StateNotifier를 사용하는 것을 권장하고 있다..
'Flutter' 카테고리의 다른 글
[Flutter/플러터] listview 안에서 scroll 하기 (0) | 2022.10.14 |
---|---|
[Flutter/플러터] Riverpod 장점 및 사용법 (1) | 2022.09.28 |
[Flutter/플러터] Riverpod를 통해 알아보는 플러터 아키텍처 - (2) Domain Model (0) | 2022.09.27 |
[Flutter/플러터] Riverpod를 통해 알아보는 플러터 아키텍처 - (1) Repository pattern (0) | 2022.09.27 |
[Flutter/플러터] Freezed 플러그인 사용하기 - (1) (0) | 2022.09.27 |