import'package:book_search/data/models/book.dart';
import'package:book_search/data/repositories/book_repository.dart';
import'package:flutter_riverpod/flutter_riverpod.dart';
// 1. 상태 클래스 만들기classHomeState{
List<Book> books;
HomeState(this.books);
}
// 2. 뷰모델 만들기 - Notifier 상속classHomeViewModelextendsNotifier<HomeState> { // Notifier 상속 시 이 뷰모델이 어떤 상태를 관리하는지 제너릭으로 명시해줄 것.@override
HomeState build() {
return HomeState([]); // 검색하기 전 최초의 상태는 북리스트가 비어있으므로 빈 리스트로 초기화.
}
// 사용자가 검색했을 때 데이터를 가지고 와서 이 뷰모델의 상태를 업데이트 해줄 수 있는 메서드.void searchBooks(String query) async {
final bookRepository = BookRepository();
final books = await bookRepository.searchBooks(query); // Book으로부터 전달받은 쿼리를 가져오도록. -> async - await 걸어서 동기화.
state = HomeState(books); // 결과를 가져왔으니 상태를 업데이트 해줌. state에 새로운 객체 HomeState(books)로 업데이트 하도록.
}
}
// 3. 뷰모델 관리자 만들기 - NotifierProvider 객체final homeViewModelProvider = NotifierProvider<HomeViewModel, HomeState>(() { // 이 관리자가 어떤 뷰모델을 관리하는지(HomeViewModel), 그 뷰모델은 어떤 상태를 가지고 있는지(HomeState)를 알려줘야 함.return HomeViewModel();
});
📍 git push
뷰모델 테스트
test/home_view_model_test.dart 생성
import'package:book_search/presentation/home/home_view_model.dart';
import'package:flutter_riverpod/flutter_riverpod.dart';
import'package:flutter_test/flutter_test.dart';
void main() {
test("HomeViewModel test", () async {
// 복습!!// 플러터에서 riverpod 사용할 때, 뷰모델 공급받을 때 ProviderScope 내에 있어야만 공급받을 수 있음.// ConsumerWidget을 통해 WidgetRef라는 타입의 ref변수를 통해서 참조 했었음.// 앱 내에서는 ProviderScope 안에서 뷰모델을 관리. 테스트 환경에서는 Widget 을 생성하지 않고 테스트 할 수 있게 ProviderContainer 제공final providerContainer = ProviderContainer();
addTearDown(providerContainer.dispose);
final HomeVm = providerContainer.read(homeViewModelProvider.notifier);
// 처음 HomeViewModel의 상태 => 빈 리스트 연결 테스트
providerContainer.read(homeViewModelProvider);
final firstState = providerContainer.read(homeViewModelProvider);
expect(firstState.books.isEmpty, true);
// HomeViewModel에서 searchBooks 호출 후 상태가 정상적으로 변경되는지 테스트await HomeVm.searchBooks('harry');
final afterState = providerContainer.read(homeViewModelProvider);
expect(afterState.books.isEmpty, false);
afterState.books.forEach((element){
print(element.toJson());
});
});
}
Book 입력 시 자동완성되도록 하여 /data/models/book.dart를 임포트 해줘야 한다.
생성자 생성
→ HomePage(home_page.dart)에 빨간 줄 생성됨. why? → 바텀시트에서 반환할 HomeBottomSheet 클래스는 생성자에서 book 변수를 갖는다고 방금 설정했는데, HomePage에 설정된 바텀시트에는 변수가 없기 때문 → 여기에도 book 넣어주어서 HomePage와 바텀시트를 연결해준다. 이 때의 book은 당연히 Book 클래스의 변수인 book이고, 입력할 때 자동완성 기능을 활용하여 Book클래스의 변수 book이 입력되도록 한다.
전달받은 book 객체에 해당하는 데이터로 수정
이미지: (현재) url → (수정) book.image
제목: (현재) “해리포터” → (수정) book.title
저자: (현재) “J.K.롤링” → (수정) book.author
각 항목은 최대 2줄이 넘어가지 않도록 설정: maxLines: 2
📍git push : “bottomSheet 변수 연결”
디테일 페이지 작업
detail_page.dart
DetailPage 클래스 내에 Book book 정의
→ book.dart 임포트
생성자 생성
home_bottom_sheet.dart 의 빨간 줄 수정: DetailPage에서 호출하는 변수 넣어주기.