해결된 질문
작성
·
42
1
안녕하세요 선생님 !!
강의 잘보고 있습니다.
Provider : 수신측에 변경 사항을 알리지 않음 라고 하셔서
코드를 작성해보았습니다.
countprovider안에서 ref.watch(towProvider) 사용해봤는데요
우선 여기서 watch를 써서 상태가 바뀐건 이해합니다.
그래서 "counter 생성자" 가 계속 출력되고요 .
근데 main함수에서 counterProvider 를 ref.watch했는데 화면이 계속 갱신 되는 건 이해가 가지 않습니다.
수신측에 변경 사항을 알리지 않음 이라고 하셔서 여기서는 호출해도 변함이 없겠구나 라고 생각했습니다...
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final towProvider= NotifierProvider<Two, int>(
(){return Two();}
);
final counterProvider = Provider<Counter>((ref) {
print("hello");
int num=ref.watch(towProvider);
return Counter(num:num);});
class Two extends Notifier<int>{
Two(){
print("Two 생성자");
}
@override
int build() => 0;
int add() => state++;
}
class Counter {
Counter ({required this.num}){
print("Counter 생성자");
}
int num;
int getIncreasedNumber() => num ++;
}
void main() {
runApp(
const ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
),
);
}
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
print("build");
Counter counter = ref.watch(counterProvider);
return Scaffold(
body: Center(
child: Text(
"${counter.num}",
style: const TextStyle(
fontSize: 24,
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){ref.read(towProvider.notifier).add();},
child: const Icon(Icons.add),
),
);
}
}
답변 1
1
안녕하세요 유하님
ref.watch
는 Provider에서 전달받은 상태가 변경되는 경우 위젯을 rebuild를 하는 방식으로 동작합니다.
Provider 자체는 내부적으로 상태가 갱신될 일이 없기 때문에 ref.watch
로 접근해도 화면이 갱신될 일이 없는게 맞으며 이 부분을 강의에선 변경사항을 알리지 못한다고 표현하였습니다. 하지만 아래와 같이 ref.watch
에 의해서 매번 새로운 Counter 인스턴스가 반환되는 경우 화면이 갱신되는게 맞습니다.
final counterProvider = Provider<Counter>((ref) {
int num = ref.watch(towProvider);
return Counter(num:num);
});
감사합니다 :)
ref.watch(counterProvider)
를 호출하는 경우, 무조건 Counter()
인스턴스를 새롭게 만들어서 반환하는 방식으로 동작하지 않습니다. 첫 호출시에만 Counter()
를 생성해서 내부적으로 들고 있고, 이후에 요청이 들어오면 내부적으로 변경 사항이 없는 경우 처음에 만들어둔 객체를 그대로 반환합니다. 공식 문서에선 캐싱 기능이라고 표현합니다. (autoDispose
로 생성하는 경우에는 해당 Provider에 대한 참조가 없다면 제거될 수 있습니다. 자세한 사항은 공식 문서를 참고해 주세요.)
Provider<Counter>
는 내부에 상태가 없기 때문에 자체적으로 상태 변화를 일으킬 수 없으므로 Provider 내부에 ref.watch
가 없다면 한 번 생성한 객체를 계속 들고 있으며 변경된 값을 반환할 수 없습니다.
아하 감사합니다.
그럼 추가적으로 궁금한 것이 생겼습니다.
새로운 Counter 인스턴스가 반환되서 => 갱신되는 거라고 하셨는데
다시 ref.watch를 빼고 다시 실행했을때는, 어떻게 보면 이때도 새로운 인스턴스가 반환되는 것 아닌가요? 앞에 const 키워드를 붙이지 않아서요... !