พื้นฐาน Cloud Firestore
อ่านและเขียนข้อมูลแบบเรียลไทม์
พื้นฐาน Cloud Firestore เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
Cloud Firestore คืออะไร
Cloud Firestore คือฐานข้อมูล NoSQL ของ Firebase ที่ยืดหยุ่นและปรับขนาดได้ โดยจัดเก็บข้อมูลเป็น เอกสาร ซึ่งจัดกลุ่มอยู่ใน คอลเลกชัน
- เอกสาร คือชุดฟิลด์คีย์/ค่า (คล้ายออบเจ็กต์ JSON)
- คอลเลกชัน คือภาชนะที่เก็บเอกสาร
- เอกสารสามารถมี คอลเลกชันย่อย ทำให้เกิดโครงสร้างแบบต้นไม้
Firestore ยังรองรับ การอัปเดตแบบเรียลไทม์ และทำงานแบบ ออฟไลน์ ได้ทันทีโดยไม่ต้องตั้งค่าเพิ่มเติม
รับอินสแตนซ์ Firestore
เข้าถึงฐานข้อมูลผ่าน Firebase.firestore จากนั้นเข้าถึงคอลเลกชันด้วย collection("name") และเข้าถึงเอกสารเฉพาะรายการด้วย document("id")
การสร้างข้อมูลอ้างอิงใช้ทรัพยากรน้อย เพราะข้อมูลอ้างอิงเหล่านี้อธิบายเพียง ตำแหน่ง ไม่ใช่ตัวข้อมูลเอง
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
val db = Firebase.firestore
val usersRef = db.collection("users")
val oneUser = db.collection("users").document("abc123")ออกแบบโครงสร้างข้อมูล
Firestore จับคู่กับ คลาสข้อมูล ของ Kotlin ได้อย่างลงตัว พร็อพเพอร์ตีแต่ละรายการจะกลายเป็นฟิลด์ในเอกสาร
กำหนดให้มี ตัวสร้างที่ไม่มีอาร์กิวเมนต์ (ค่าปริยายจะจัดการเรื่องนี้ให้) เพื่อให้ Firestore แปลงเอกสารกลับเป็นออบเจ็กต์ได้
data class Note(
val title: String = "",
val body: String = "",
val done: Boolean = false,
val createdAt: Long = 0L
)เขียนเอกสาร
ใช้ set เพื่อสร้างหรือเขียนทับเอกสาร ให้ Firestore สร้าง ID ด้วย add หรือเลือก ID เองด้วย document(id).set(...)
คำสั่งเหล่านี้ส่งคืน Task และเมื่อใช้โครูทีน คุณสามารถใช้ await() กับคำสั่งเหล่านี้ได้
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun addNote(note: Note): String {
val ref = Firebase.firestore
.collection("notes")
.add(note) // auto-generated ID
.await()
return ref.id
}อ่านเอกสาร
get() จะดึงเอกสารหนึ่งครั้ง แปลงเอกสารนั้นเป็นคลาสข้อมูลของคุณด้วย toObject(Note::class.java)
ตรวจสอบ exists() เสมอ เพราะการอ้างอิงเอกสารที่ไม่มีอยู่จะส่งคืนสแนปชอตที่ไม่มีเอกสารนั้นจริง
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun loadNote(id: String): Note? {
val snapshot = Firebase.firestore
.collection("notes")
.document(id)
.get()
.await()
return if (snapshot.exists()) snapshot.toObject(Note::class.java) else null
}อัปเดตและลบ
update เปลี่ยนฟิลด์ที่ระบุโดยไม่กระทบส่วนที่เหลือของเอกสาร ส่วน delete จะลบเอกสารทั้งหมด
ใช้ set(..., SetOptions.merge()) หากต้องการเขียนข้อมูลเพียงบางส่วน และต้องการให้สร้างเอกสารด้วยเมื่อเอกสารนั้นยังไม่มี
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun markDone(id: String) {
Firebase.firestore.collection("notes").document(id)
.update("done", true)
.await()
}
suspend fun removeNote(id: String) {
Firebase.firestore.collection("notes").document(id)
.delete()
.await()
}สืบค้นคอลเลกชัน
สร้างคำค้นด้วยการเชื่อมตัวกรองต่อกัน ได้แก่ whereEqualTo, whereGreaterThan, orderBy, limit และอื่น ๆ
คำค้นจะส่งคืน QuerySnapshot ให้ไล่ดูเอกสารในนั้นเพื่อแปลงแต่ละรายการเป็นโมเดลของคุณ
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.tasks.await
suspend fun pendingNotes(): List<Note> {
val snap = Firebase.firestore.collection("notes")
.whereEqualTo("done", false)
.orderBy("createdAt")
.limit(20)
.get()
.await()
return snap.documents.mapNotNull { it.toObject(Note::class.java) }
}ตัวติดตามแบบเรียลไทม์
จุดเด่นของ Firestore คือการทำงานแบบ เรียลไทม์ addSnapshotListener จะส่งข้อมูลปัจจุบันให้ทันที จากนั้นส่งการเปลี่ยนแปลงทุกครั้งโดยอัตโนมัติ
คำสั่งนี้ส่งคืน ListenerRegistration ให้เรียก remove() เมื่อใช้งานเสร็จเพื่อหยุดรับการอัปเดต
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
val registration = Firebase.firestore.collection("notes")
.whereEqualTo("done", false)
.addSnapshotListener { snapshot, error ->
if (error != null || snapshot == null) return@addSnapshotListener
val notes = snapshot.toObjects(Note::class.java)
println("Now have ${notes.size} pending notes")
}
// Later: registration.remove()ข้อมูลเรียลไทม์ในรูปแบบ Flow
ใน Compose แนวทางมาตรฐานคือเปิดเผยข้อมูล Firestore เป็น Kotlin Flow โดย callbackFlow จะเชื่อมการเรียกกลับของตัวติดตามเข้ากับโฟลว์ และ awaitClose จะลบตัวติดตามเมื่อหยุดรวบรวมข้อมูล
import com.google.firebase.Firebase
import com.google.firebase.firestore.firestore
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
fun notesFlow(): Flow<List<Note>> = callbackFlow {
val reg = Firebase.firestore.collection("notes")
.addSnapshotListener { snap, err ->
if (err == null && snap != null) {
trySend(snap.toObjects(Note::class.java))
}
}
awaitClose { reg.remove() }
}แสดงข้อมูลใน Compose
รวบรวมโฟลว์ด้วย collectAsStateWithLifecycle() แล้วแสดงผลใน LazyColumn รายการจะอัปเดตตัวเองทุกครั้งที่ Firestore เปลี่ยนแปลง — ไม่ต้องรีเฟรชด้วยตนเอง
@Composable
fun NotesScreen(viewModel: NotesViewModel) {
val notes by viewModel.notes.collectAsStateWithLifecycle()
LazyColumn {
items(notes) { note ->
ListItem(
headlineContent = { Text(note.title) },
supportingContent = { Text(note.body) }
)
}
}
}กฎความปลอดภัยมีความสำคัญ
โดยค่าเริ่มต้น Firestore จะถูกล็อกไว้ กฎความปลอดภัย เป็นตัวกำหนดว่าใครอ่านหรือเขียนแต่ละเส้นทางได้บ้าง กฎเหล่านี้ทำงานบนเซิร์ฟเวอร์และไคลเอ็นต์ไม่สามารถข้ามได้
กฎที่ใช้บ่อยคือ ผู้ใช้จะเข้าถึงได้เฉพาะข้อมูลของตนเอง โดยใช้ uid ของการยืนยันตัวตนเป็นคีย์
// firestore.rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId}/{document=**} {
allow read, write: if request.auth != null
&& request.auth.uid == userId;
}
}
}ตรวจสอบความเข้าใจ
คุณต้องการรายการ Compose ที่อัปเดตทันทีเมื่อข้อมูล Firestore ต้นทางเปลี่ยนแปลง โดยไม่ต้องรีเฟรชด้วยตนเอง คุณควรใช้ API ใด
สรุป: Firestore
ตอนนี้คุณสามารถจัดเก็บและซิงค์ข้อมูลด้วย Cloud Firestore ได้แล้ว:
- ข้อมูลจะอยู่ในรูปของ เอกสารภายใน คอลเลกชัน และสร้างโมเดลด้วยคลาสข้อมูลของ Kotlin
- เขียนด้วย
add/setอ่านด้วยgetและเปลี่ยนแปลงด้วยupdate/delete - สืบค้นด้วย
whereEqualTo,orderBy,limit - ใช้
addSnapshotListener(หรือcallbackFlow) สำหรับ UI แบบ เรียลไทม์ - ปกป้องข้อมูลด้วย กฎความปลอดภัย ที่ใช้
request.auth.uidเป็นคีย์
ถัดไป: ติดต่อผู้ใช้เมื่อแอปปิดอยู่ด้วย Cloud Messaging
คำถามที่พบบ่อย
บทเรียน “พื้นฐาน Cloud Firestore” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พื้นฐาน Cloud Firestore” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐาน Cloud Firestore”
อ่านและเขียนข้อมูลแบบเรียลไทม์ คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “พื้นฐาน Cloud Firestore” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม
ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การตั้งค่า Firebase
- การยืนยันตัวตนด้วย Firebase
- พื้นฐาน Cloud Firestore
- การพุชด้วย Cloud Messaging