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
image

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();
          },
        ),
      ),
    );
  }
}
⚠️ **GitHub.com Fallback** ⚠️