0Pricing
Android Academy · درس

نمط Repository

افصلوا الوصول إلى البيانات عن واجهة المستخدم باستخدام نمط Repository. نسّقوا بين قاعدة بيانات Room وواجهة الشبكة API باعتبارهما مصدرَي الحقيقة الوحيدين.

نمط Repository درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 4 من أصل 6. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Android Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Android Academy 6 دروس في المجموع.

لماذا نستخدم Repository؟

مع ازدياد حجم تطبيقك، قد يمتلئ ViewModel بشيفرة الوصول إلى البيانات (استعلامات Room واستدعاءات Retrofit وقراءات SharedPreferences).

ينقل نمط Repository كل عمليات الوصول إلى البيانات خلف فئة واحدة. ولا يتعامل ViewModel إلا مع Repository، إذ لا يحتاج إلى معرفة مصدر البيانات.

طبقات البنية

تتكون بنية Android الموصى بها من ثلاث طبقات:

  • طبقة واجهة المستخدم — يعرض Activity/Fragment البيانات ويرسل أحداث المستخدم
  • ViewModel — يحتفظ بالحالة، ويعالج الأحداث، ويستدعي Repository
  • Repository — يجلب البيانات من Room (محليًا) أو Retrofit (عن بُعد)، ويقرر المصدر الذي سيستخدمه

Repository بسيط

أنشئ فئة Repository تلتف حول DAO وواجهة API البعيدة:

class NoteRepository(private val dao: NoteDao) {

    // Expose a Flow that emits whenever data changes
    val allNotes = dao.getAllNotes()

    suspend fun insert(note: Note) {
        dao.insert(note)
    }

    suspend fun delete(note: Note) {
        dao.delete(note)
    }

    suspend fun update(note: Note) {
        dao.update(note)
    }
}

يستخدم ViewModel الـ Repository

يحصل ViewModel على البيانات من Repository، وليس مباشرةً من DAO:

class NoteViewModel(private val repo: NoteRepository) : ViewModel() {

    val notes = repo.allNotes  // Flow from Repository

    fun addNote(title: String, body: String) {
        viewModelScope.launch {
            repo.insert(Note(title = title, body = body))
        }
    }

    fun deleteNote(note: Note) {
        viewModelScope.launch {
            repo.delete(note)
        }
    }
}

استراتيجية التخزين المؤقت أولًا

من أنماط Repository الشائعة: التخزين المؤقت أولًا. اعرض البيانات المخزنة مؤقتًا محليًا فورًا، ثم حدّثها من الشبكة في الخلفية:

  • 1. إصدار البيانات المخزنة مؤقتًا من Room فورًا
  • 2. جلب البيانات الحديثة من API
  • 3. حفظها في Room — ويحدّث Flow البيانات تلقائيًا

يوفر ذلك أوقات تحميل سريعة وبيانات تصبح حديثة في النهاية.

تنفيذ استراتيجية التخزين المؤقت أولًا

حدّث قاعدة البيانات المحلية من الشبكة:

class ProductRepository(
    private val dao: ProductDao,
    private val api: ProductApiService
) {
    // Room Flow emits local data immediately
    val products = dao.getAllProducts()

    // Call this to sync with the server
    suspend fun refresh() {
        try {
            val remoteProducts = api.getProducts()
            dao.insertAll(remoteProducts)  // overwrites local cache
        } catch (e: Exception) {
            // Network failed — cached data is still shown
        }
    }
}

ViewModelFactory

عندما يحتوي ViewModel على معاملات في المُنشئ، تحتاج إلى ViewModelFactory لإنشائه:

class NoteViewModelFactory(
    private val repo: NoteRepository
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        @Suppress("UNCHECKED_CAST")
        return NoteViewModel(repo) as T
    }
}

// In Activity:
val db = NoteDatabase.getInstance(this)
val repo = NoteRepository(db.noteDao())
val factory = NoteViewModelFactory(repo)
val viewModel = ViewModelProvider(this, factory)[NoteViewModel::class.java]

Hilt لحقن الاعتماديات

يصبح إنشاء مثيلات Repository وViewModel يدويًا أمرًا مرهقًا في التطبيقات الكبيرة. تعمل Hilt (حقن الاعتماديات) على أتمتة ذلك:

  • ضع التعليقات التوضيحية @HiltViewModel و@Inject على فئاتك
  • تنشئ Hilt الاعتماديات وتوفرها تلقائيًا
  • تلغي كل الشيفرة المتكررة الخاصة بـ factory

ملخص الفوائد

يوفر نمط Repository ما يلي:

  • قابلية الاختبار — استبدال API الحقيقي ببديل وهمي لاختبارات الوحدة
  • فصل المسؤوليات — لا يعرف ViewModel ما إذا كانت البيانات محلية أو بعيدة
  • مصدر واحد للحقيقة — يكون Room هو المصدر دائمًا، بينما يقتصر دور API على تحديثه
  • المرونة — إضافة التخزين المؤقت أو تقسيم الصفحات أو مصادر بيانات جديدة من دون تعديل ViewModel

تحقّق سريع

ما المسؤولية الأساسية لـ Repository في بنية Android؟

مراجعة: نمط Repository

أصبحت تفهم الآن بنية Android الموصى بها:

  • UI → ViewModel → Repository → (Room / Retrofit)
  • Repository هو مصدر الحقيقة الوحيد
  • التخزين المؤقت أولًا: عرض البيانات المحلية فورًا وتحديثها في الخلفية
  • استخدم ViewModelFactory عندما يحتوي ViewModel على معاملات في المُنشئ
  • تعمل Hilt على أتمتة حقن الاعتماديات في التطبيقات الأكبر

المقرر الأخير: الشبكات والتحسينات — Retrofit والصور والنشر.

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

هل درس «نمط Repository» مجاني؟

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

ماذا ستتعلم في «نمط Repository»؟

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

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

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

كم من الوقت يستغرق درس «نمط Repository»؟

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

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

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

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

  1. ViewModel وLiveData
  2. قاعدة بيانات Room
  3. Coroutines والدوال المعلّقة
  4. نمط Repository
  5. مكوّن Navigation
  6. حقن التبعيات باستخدام Hilt
← العودة إلى Android Academy