Skip to main content

4 posts tagged with "FutureProvider"

View All Tags

· One min read
Park Ki Hyun

invalidate​


onPressed: () async {
ref.invalidate(userDetailProvider);
},

refresh할 때 invalidate를 사용한다면 위처럼 onPressed 함수를 구현할 수 있습니다. 물론 skipLoadingOnRefresh도 적용했습니다.

invalidate의 인자값 타입은 ProviderOrFamily이다. 그래서 Family를 주지 않고 적용한다면 모든 provider가 auto dispose된다.

refresh​


onPressed: () async {
return ref.refresh(userDetailProvider(userId));
},

또는

onPressed: () {
return ref.refresh(userDetailProvider(userId).future);
},

refresh 인자 타입은 Family Provider라면 family값을 넘겨주어야 한다. 그리고 return을 사용해야 하기에 return값이 없다면 invalidate를 추천한다.

· One min read
Park Ki Hyun

skipLoadingOnRefresh​


when 메서드에서 skipLoadingOnRefresh라는 메서드가 있는데 true가 디폴트다. 새로고침해도 loading 창 안보여주는건데 false로 해주는 편이 좋다.

새로고침​


ref.refresh() 또는 ref.invalidate()를 사용한다. 예시로는 RefreshIndicator로 했지만 버튼으로 하는게 좋은 UI라고 하는 듯

그리고 윈도우에서는 RefreshIndicator 동작안한다..

freezed class override​



class User with _$User {
const User._();

...

String toString() => 'User(id:$id)';
}

freezed data class 에서 User._()를 선언하고 toString을 다시 오버라이딩 할 수 있던데 이에 대해서 조금 더 알아봐야 할 듯

· 3 min read
Park Ki Hyun

가상 API​


여기 에서 다양한 API를 제공해준다.

users API로 FutureProvider 실습을 한다.

autoDispose 사용 여부​


만약 특정 페이지 진입 시 API를 통해서 값을 가져왔을 때 이 값을 캐싱 할 것이면 autoDispose 사용하면 안되고 다시 안 가져올 것이면 autoDispose 사용하는 것이 좋다.

설정값 같은 경우는 API를 쏴서 변경하는 경우가 거의 없으므로 캐싱 하는 것이 좋다.

future provider body​


when​

값을 불러올 때 when을 사용한 모습입니다.

body: userList.when(
data: (users) {
return ListView.separated(
itemCount: users.length,
separatorBuilder: (context, index) {
return const Divider();
},
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
leading: CircleAvatar(
child: Text(user.id.toString()),
),
title: Text(user.name),
);
},
);
},
error: (e, st) {
return Text(
e.toString(),
style: const TextStyle(fontSize: 20, color: Colors.red),
);
},
loading: () => const Center(
child: CircularProgressIndicator(),
),
),

switch expression​

값을 불러올 때 switch를 사용한 모습입니다.

body: switch (userList) {
AsyncData(value: final users) => ListView.separated(
itemCount: users.length,
separatorBuilder: (context, index) {
return const Divider();
},
itemBuilder: (context, index) {
final user = users[index];
return ListTile(
leading: CircleAvatar(
child: Text(user.id.toString()),
),
title: Text(user.name),
);
},
),
AsyncError(error: final e) => Text(
e.toString(),
style: const TextStyle(fontSize: 20, color: Colors.red),
),
_ => const Center(
child: CircularProgressIndicator(),
),
},

마지막에 원래 _ 대신 AsyncLoading이 들어가야 하지만 무슨 에러가 난다.

userListProvider를 @Sealed로 만들었어야 한다고 한다.

keepalive​


하면서 궁금증이 생겼었는데 값을 가져왔으면 다시 나갔다 왔을 때 loading 안 보고 싶었습니다.

그러면 autoDispose일 때 ref.keepAlive()를 사용하면 됩니다.
주의할 점은 http 호출이 끝나고 적용해야 합니다.

값을 가져온 것을 성공한 페이지는 값이 유지가 되고(dispose안함) error가 나면 dispose 합니다.

· 2 min read
Park Ki Hyun

state provider​


특징으로는 code generator가 안되고

state를 갖고 있다는 점

floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider.notifier).state++;
},
child: const Icon(Icons.add),
),

위와 같이 read를 하는데 notifier를 사용해서 state에 접근할 수 있다.

그리고 추가로 UI를 그리려면 Future.delay 또는 Listen을 사용할 수 있다.
(그냥 그리려면 에러난다. 충돌나서)

ref.listen<int>(counterProvider, (previous, next) {
if (next == 3) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text('counter : $next'),
);
},
);
}
});

요런식으로 listen할 수 있다. 이전 값 다음 값이 있다.

update​


onPressed: () {
ref
.read(autoDisposecounterProvider.notifier)
.update((state) => state + 10);
},

위 코드는

ref.read(autoDisposecounterProvider.notifier).state + 
ref.read(autoDisposecounterProvider.notifier).state + 10

과 같은 코드이다. 너무 길기 때문에 그냥 update 사용하는 것이 편리하다.

state를 인자로 사용할 로직이 필요하면 update 사용하기

Future Provider의 이야기​


remote api를 호출하면 3가지 상태 처리가 필요하다.

in progress, success, error이다.

3가지 모두 동시에 2가지 이상 상태가 될 수 없다.

FutureProvider는 이 3가지 상태에 대한 값을 처리해준다.

AsyncData, AsyncError, AsyncLoading이 있다.

생성자도 3가지 있다.

AsyncValue가 중요하다는 뜻

소소한 팁​


  1. provider 안에 ref.read()를 사용하지 말 것

  2. StateProvider 대신 NotifierProvider 사용할 것