의존성이 결합된 구조 → 의존성을 제거한 더 나은 대안
Model
1. 데이터를 제공하는 공통 인터페이스를 제공
abstract class Repository {
Future<List<Chat>> getChatList();
}
구현체가 여러가지일 경우를 대비해 추상 클래스로 만든다. (구현체가 여러가지가 아닌 경우에는 추상 클래스를 꼭 만들 필요는 없다.)
2. 구체화한 객체를 구현
class LocalRepository extends Repository {
Future<List<Chat>> getChatList() async {
Future.delayed(Duration(seconds: 1));
return [
Chat('홍길동', null, 'hello world', 100234234234, 'aaa@aaa.com'),
Chat('홍길동', null, 'hello world 2hello world 2hello world 2hello world', 100234234234, 'aaa@aaa.com'),
Chat('한석봉', null, 'hello world 3', 100234234234, 'bbb@aaa.com'),
];
}
}
class FirebaseRepository extends Repository {
Future<List<Chat>> getChatList() {
// TODO: implement getChatList
throw UnimplementedError();
}
}
ViewModel
1. View 측에서 사용할 기능과 데이터 정의
class ChatViewModel extends ChangeNotifier {
final Repository<Chat> repository = FakeRepository();
List<Chat> _chatList = [];
List<Chat> get chatList => _chatList;
bool _isLoading = false;
get isLoading => _isLoading;
void fetch() {
_isLoading = true;
repository.getAll().then((value) {
_chatList = value;
_isLoading = false;
notifyListeners();
});
}
void pushMessage(String email, String text, int time) {
repository.add(Chat(
'홍길동',
'https://asd.fdsda.com/asd/adfWEazsdasdQEas',
text,
time,
email,
)).whenComplete(() {
notifyListeners();
});
}
}
ChangeNotifier를 상속하고 데이터가 변경되면(UI를 갱신해야 할 때마다) notifyListeners()를 호출
void main() {
runApp(
MultuProvider(
providers: [
ChangeNotifierProvider.value(value: ChatViewModel()),
],
child: MyApp(),
),
);
}
build(BuildContext context) {
final viewModel = context.watch<ChatViewModel>();
return Scaffold(
appBar: AppBar(
title: Text(''),
Widget
가장 이상적인 형태 = Model, View, ViewModel이 모두 독립적인 형태
비즈니스 로직 수정시 - Model 수정
UI 수정시 - View 수정
기능 수정시 ViewModel 수정
⇒ ViewModel은 Model의 구체적인 내용을 알 필요가 없다.
생성자를 통해 추상화 된 객체 타입을 받는다.
생성자를 통해 인스턴스를 전달
⇒ Model 교체가 편해짐