34일차 과제 - rlatkddbs99/Flutter GitHub Wiki
Firestore는 문서 데이터를 json형식으로 전달한다. dart에서는 String key로 접근하는데 firestore 레퍼런스를 가져올 때 withConverter함수를 사용해서 JSON이 아닌 객체 자체를 주고 받고 데이터 타입도 정할 수 있다. fromFirestore: (snapshot, _) => Post.fromMap(snapshot.data()!), 이 부분으로 firestore에선 Json이 아닌 객체로 데이터를 넘겨주고 toFirestore: (data, _) => data.toMap(), 이 부분으로 firestore에 저장할 때 객체를 Json으로 변경해서 넘겨준다. ref에 받아온 데이터 타입은 Map<String,dynamic>이 아닌 Post객체 자체가 된다. Text(snapshot.data![index].data().title) 이런 식으로 별도의 변환 없이 firestore 문서에 바로 객체처럼 접근 가능하게 된다.
개발환경 때문에 진짜 오래걸렸다.. 멘탈 개나감;;
Android.Emulator.-.flutter_emulator_5556.2023-03-15.16-53-40.mp4
main.dart
import 'package:fire/view/page/assignment_page.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: AssignmentPage(),
);
}
}
model/post.dart
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>);
}
view/page/assignment_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../../model/post.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({'likes': FieldValue.increment(1)});
@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: () => likesUp(snapshot.data![index].id),
),
),
);
}
return const SizedBox();
},
),
),
);
}
}