본문 바로가기
스파르타/Flutter

[Flutter] 숙제 Book 애플리케이션 추가 구현 - ( week 4 )

by bakcoding_sparta 2023. 4. 29.

첫 번째 목표

  • ListTile의 subtitle 자리에 작가 이름, 책 발행일 가져와서 보여주기
  • 작가 이름과 책 발행일은 줄 바꿈으로 구분
  • 작가가 여러 명인 경우 각각의 작가명을 쉼표로 구분

 

API 확인

우선 가져올 정보를 API 데이터를 보고 확인한다.

필요한 정보인 작가와 발행일은 각각 authors, publicshedDate의 이름으로 들어온다.

authors의 경우 리스트이기 때문에 받아올 때도 리스트에 담는다.

class Book {
  String id;
  String title;
  String subtitle;
  List authors;
  String publishDate;
  String thumbnail; // 썸네일 이미지 링크
  String previewLink; // ListTile 을 눌렀을 때 이동하는 링크
  Book({
    required this.id,
    required this.title,
    required this.subtitle,
    required this.authors,
    required this.publishDate,
    required this.thumbnail,
    required this.previewLink,
  });
}
          authors: item['volumeInfo']['authors'] ?? [],
          publishDate: item['volumeInfo']['publishDate'] ?? "",

이제 목록에서 해당 정보를 띄운다.

 

      subtitle: Text(
        book.authors.length > 0
            ? book.authors.join(", ") + "\n" + book.publishedDate
            : book.publishedDate,
        style: TextStyle(color: Colors.grey),
      ),

 

저자의 경우 비어있는 경우도 있기 때문에 예외처리를 해준다.

복수의 저자인 경우, 로 구분해서 하나의 문자열로 보여주기 위해서 join 함수를 사용했다.

 

 

두 번째 목표

좋아요한 책이 앱이 다시 켜져도 유지되도록 한다.

좋아요 목록을 기기에 저장하고 리스트를 가져올 때 비교한다.

장치에 정보를 저장하기 위해서 shared_preference를 사용한다.

 

패키지 설치

flutter pub add shared_preferences

 

main.dart

preferences를 어디서든 접근하기 위해서 전역으로 선언하고 main함수에서 동기로 가져온다.

late SharedPreferences prefs;

void main() async {
  // 실행전 flutter 엔진의 바인딩 검사
  WidgetsFlutterBinding.ensureInitialized();
  prefs = await SharedPreferences.getInstance();

 

book.dart

prefs에 저장할 때 json으로 변환하고 불러올 때 json에서 클래스로 변환하기 위한 함수를 만든다.

  Map toJson() {
    return {
      'id': id,
      'title': title,
      'subtitle': subtitle,
      'authors': authors,
      'publishedDate': publishedDate,
      'thumbnail': thumbnail,
      'previewLink': previewLink,
    };
  }

  factory Book.fromJson(json) {
    return Book(
      id: json['id'] ?? "",
      title: json['title'] ?? "",
      subtitle: json['subtitle'] ?? "",
      authors: json['authors'] ?? [],
      publishedDate: json['publishedDate'] ?? "",
      thumbnail: json['thumbnail'] ?? "",
      previewLink: json['previewLink'] ?? "",
    );
  }

 

book_service.dart

장치에 저장하고 불러오는 함수를 만든다.

  saveBookList() {
    List likedBookJsonList =
        likedBookList.map((book) => book.toJson()).toList();
    String jsonString = jsonEncode(likedBookJsonList);
    //print(likedBookJsonList);
    prefs.setString('likedBookList', jsonString);
  }

  loadBookList() {
    String? jsonString = prefs.getString('likedBookList');
    if (jsonString == null) return;
    List likedBookJsonList = jsonDecode(jsonString);
    likedBookList =
        likedBookJsonList.map((json) => Book.fromJson(json)).toList();
  }

 

prefs에 저장할 시점은 좋아요 버튼이 클릭될 때이다. 

  void toggleLikeBook({required Book book}) {
    String bookId = book.id;
    if (likedBookList.map((book) => book.id).contains(bookId)) {
      likedBookList.removeWhere((book) => book.id == bookId);
    } else {
      likedBookList.add(book);
    }
    notifyListeners();
    saveBookList();
  }

toggleLikeBook 함수 하단에서 저장한다.

 

정보를 불러올 시점은 앱이 시작하고 BookService가 처음 호출될 때 리스트를 로드하기 위해서 생성자에서 호출시킨다.

class BookService extends ChangeNotifier {
  BookService() {
    loadBookList();
  }

 

좋아요 이후 앱을 다시 시작해도 좋아요 한 책들이 유지되는 걸 확인할 수 있다.

 

해설 비교

정답 해설과 비교해보니 저자의 이름과 발행날짜를 Text 위젯에 넣어줄때 코드가 좀 더 간단하게 가능했다.

"${book.authors.join(", ")}\n${book.publishedDate}",

그 외에는 해설과 동일하게 코드가 작성되었다.