문제의 시작
•
AuthProvider ⇒ Firebase Authentication 을 활용해 인증 상태를 관리하는 Provider
•
UserProvider ⇒ 서비스 유저의 닉네임, 이미지 등 서비스 유저 상태를 관리하는 Provider
인증을 하면 ⇒ 인증한 사용자 정보를 가져와야 한다. 이 상황에서 Provider 간 의존성이 발생합니다.
AuthProvider 에서 인증 완료 타이밍을 UserProvider에서 catch 해야하고, AuthProvider로부터 userID를 받아와서 UserProvider는 API Server에 유저 정보를 요정해야 하는 상황입니다.
이때 사용하는게 ProxyProvider입니다. 관련되어 Google, Stack Overflow 에 많은 검색을 해봤지만 예제 코드만 존재하고, 다른 사례에 적용할 때 근거가 되는 왜? 가 부족해서 고생을 좀 했습니다.
우선 예제코드 분석,
Job, Person
`Provider` suffix를 안붙이고 쓰네요.
아래 코드를 살펴보면 Job은 Person 을 변수로 들고 있습니다. Person이 변경되면 그에 따라 Job도 변경되어야 함을 알 수 있습니다. 이것을 이해하고 ProxyProvider를 봐야합니다.
class Person with ChangeNotifier {
Person({this.name, this.age});
final String name;
int age;
void increaseAge() {
this.age++;
notifyListeners();
}
}
class Job with ChangeNotifier {
Job(
this.person, {
this.career,
});
final Person person;
String career;
String get title {
if (person.age >= 28) return 'Dr. ${person.name}, $career PhD';
return '${person.name}, Student';
}
}
Dart
복사
다음 ProxyProvider를 사용하는 예제,
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<Person>(create: (_) => Person(name: 'Yohan', age: 25)),
ChangeNotifierProxyProvider<Person, Job>(
create: (BuildContext context) => Job(Provider.of<Person>(context, listen: false)),
update: (BuildContext context, Person person, Job job) => Job(person, career: 'Vet'),
),
],
child: MyApp(),
),
);
}
Dart
복사
의존성이 없는 Person을 먼저 생성합니다.
그 후 Person 에 의존성이 있는 Json 을 ChangeNotifierProxyProvider 를 활용해 생성합니다.
ChangeNotifierProvider<A, A 를 의존하는 B>(
create: (BuildContext context) => { B Provider 생성 },
update: (BuildContext context, A a, B b) => { 파라미터로 넘어온 A를 활용해 B를 업데이트 하는 코드 작성 }
)
Dart
복사
결과물
class _AppState extends State<App> {
void initState() {
super.initState();
}
Widget build(BuildContext context) {
return MaterialApp(
home: MultiProvider(
providers: [
ChangeNotifierProvider<AuthProvider>(create: (_) => AuthProvider()),
ChangeNotifierProxyProvider<AuthProvider, UserProvider>(
create: (BuildContext context) => UserProvider(),
update: (BuildContext context, AuthProvider authProvider, UserProvider userProvider) => userProvider.updateFirebaseUser(authProvider.getUser())
)
],
child: RootPage(),
)
);
}
}
Dart
복사