0Pricing
Android Academy · درس

أساسيات Cloud Firestore

اقرأ البيانات الآنية واكتبها

أساسيات Cloud Firestore درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 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 تنشئ معرّفًا باستخدام add، أو اختر معرّفك بنفسك باستخدام document(id).set(...).

تُرجع هذه الاستدعاءات كائنات Tasks؛ ومع coroutines يمكنك استخدام 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 استدعاء المستمع بـ flow، بينما يزيل 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

اجمع flow باستخدام 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 الأساسية، دون تحديث يدوي. ما واجهة برمجة التطبيقات التي تستخدمها؟

مراجعة: Firestore

يمكنك الآن تخزين البيانات ومزامنتها باستخدام Cloud Firestore:

  • توجد البيانات على شكل مستندات داخل مجموعات؛ ونمذجها باستخدام فئات بيانات Kotlin.
  • اكتب باستخدام add/set، واقرأ باستخدام get، وغيّر باستخدام update/delete.
  • أجرِ الاستعلامات باستخدام whereEqualTo وorderBy وlimit.
  • استخدم addSnapshotListener (أو callbackFlow) لإنشاء واجهة مستخدم آنية.
  • احمِ البيانات باستخدام قواعد الأمان المعتمدة على request.auth.uid.

التالي: الوصول إلى المستخدمين عندما يكون التطبيق مغلقًا باستخدام Cloud Messaging.

الأسئلة الشائعة

هل درس «أساسيات Cloud Firestore» مجاني؟

نعم — نص درس «أساسيات Cloud Firestore» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Android Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Android Academy 4 دروس في المجموع.

ماذا ستتعلم في «أساسيات Cloud Firestore»؟

اقرأ البيانات الآنية واكتبها تتمرن على Android Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Android Academy؟

لا تُشترط خبرة سابقة. Android Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «أساسيات Cloud Firestore»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Android Academy هذا؟

نعم. كل درس في Android Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. إعداد Firebase
  2. المصادقة باستخدام Firebase
  3. أساسيات Cloud Firestore
  4. الدفع باستخدام Cloud Messaging
← العودة إلى Android Academy