34일차
과제를 진행하기 위해서 아래의 설정을 맞춰주세요.
프로젝트에 컬렉션 (post)를 만들고 2가지 Document를 만들어 다음의 값을 넣도록 한다.
- 문서명은 자동생성할 수 있도록 한다.
- 필드값은 content, likes, title를 같도록 하며, 데이터타입은 다음과 같다.
- content - string
- title - string
- likes - number
- 지금까지 JSON 데이터를 불러와서 Class에 적용시키기 위해 Serialization을 진행하였다. Firebase에서 이를 편하게 적용시킬 수 있도록하는 메서드 (withConverter)를 제공하는데,
- lib/model/post.dart
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';
class Post {
String? id;
String title;
String content;
int likes;
Post({
required this.id,
required this.title,
required this.content,
required this.likes,
});
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'title': title,
'content': content,
'likes': likes,
};
}
factory Post.fromMap(Map<String, dynamic> map) {
return Post(
id: map['id'] as String?,
title: map['title'] as String,
content: map['content'] as String,
likes: map['likes'] as int,
);
}
String toJson() => json.encode(toMap());
factory Post.fromJson(String source) =>
Post.fromMap(json.decode(source) as Map<String, dynamic>);
}
lib/view/page/assignment_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class AssignmentPage extends StatefulWidget {
const AssignmentPage({super.key});
@override
State<AssignmentPage> createState() => _AssignmentPageState();
}
class _AssignmentPageState extends State<AssignmentPage> {
var ref = FirebaseFirestore.instance.collection('post').withConverter(
fromFirestore: (snapshot, _) => Post.fromMap(snapshot.data()!),
toFirestore: (data, _) => data.toMap(),
);
Future<List<QueryDocumentSnapshot<Post>>> readData() async {
var items = await ref.get();
return items.docs;
}
// likesUp(String id) => ref.doc(id).update(...);
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: FutureBuilder<List<QueryDocumentSnapshot<Post>>>(
future: readData(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) => ListTile(
title: Text(snapshot.data![index].data().title),
subtitle: Text(snapshot.data![index].data().content),
trailing: IconButton(
icon: const Icon(Icons.favorite),
onPressed: (){},
// onPressed: () => likesUp(snapshot.data![index].id),
),
),
);
}
return const SizedBox();
},
),
),
);
}
}
firestore에서 받아온 json 데이터를 가지고 데이터모델을 만들면 일반 객체로 접근이 가능하다.타입도 안전하게 지켜지고 , String key로 접근하다 실수하는 일도 없어진다.
그런데 모델이 많아지면 일일이 받아오는 것이 쉽지않다.
그래서 firestore 레퍼런스를 가져올때 withConverter 함수를 사용해서 JSON이 아닌 객체를 주고 받고 그 데이터 타입도 정해줄 수 있다.
var ref = FirebaseFirestore.instance.collection('post').withConverter(
//firestore에서 JSON이 아닌 객체로 데이터를 넘겨줌
fromFirestore: (snapshot, _) => Post.fromMap(snapshot.data()!),
//firestore에 저장할 때 객체를 Json으로 변경해서 넘겨줌
toFirestore: (data, _) => data.toMap(),
);
이렇게하면 얻어온 데이터 타입은 JSON(Map<String,dynamic>이 아닌 Post 객체다. 이제 별도의 변환없이 firestore 문서에 바로 객체처럼 접근할 수 있다.
위의 제공된 코드의 주석을 처리하면 다음과 같이 구현이 가능하다. trailing의 IconButton을 클릭하면 해당 포스트의 좋아요 수가 +1만큼 올라간다. 주석을 해제하고, 코드를 알맞게 작성하시오.
FieldValue를 사용하여 해결할 것
위에 주석처리된 부분
likes가 1씩 증가하도록 업데이트한다.
[참고]
https://velog.io/@allegromoth/Flutter-%EC%95%B1%EA%B3%BC-Firebase-%EC%97%B0%EB%8F%99
플러터앱과 firebase연동 오류들...
https://engschool.tistory.com/160
withConverter