انشاء المستودع بـ Paging

Mohammad Laifمنذ سنة

بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته

في هذا الدرس (يعتبر درس لاحق بالسابق) سنتعلم كيفية انشاء كلاس مستودع للبيانات مع الـ Paging و الـ LiveData باستخدام نمط الـ Repository حتى نهيئ المشروع لإنشاء قاعدة بيانات باستخدام الـ Room. لمعرفة المزيد حول الـ Paging راجع الدرس (استخدام الـ Paging في الـ DAO) و المصادر.

 

ماذا سننشئ؟

  • كلاس Repository لعناصر الـ Card.

 

انشاء كلاس الـ Repository.

نقوم بانشاء كلاس جديدة باسم CardRepository, وحقولها كالتالي: ننشئ عنصر منها (لاننا سنستخدمتها كـ Singleton) وحقل اخر للـ CardDao:

public class CardRepository {
    private static CardRepository sInstance;
    private final CardDao mCardDao;
}

 

نقوم بانشاء Constructor يأخد Application (تستطيع جعله يأخد AppDatabase اذا احببت) من خلاله نقوم بعمل init لكل من حقولنا السابقه كـ لقاعدة البيانات و الـ Dao:

private CardRepository(Application application) {
    AppDatabase db = AppDatabase.getInstance(application);
    mCardDao = db.cardDao();
}

 

ثم ننشئ دالة تقوم بارجاع لنا هذه الكلاس كـ Singelton:

    public static CardRepository getInstance(Application application) {
        if (sInstance == null) {
            synchronized (CardRepository.class) {
                if (sInstance == null) {
                    sInstance = new CardRepository(application);
                }
            }
        }
        return sInstance;
    }

 

الان الاختلاف بين هذا الـ Repository والسابق هو كيفية جلب البيانات, ننشئ دالة تقوم بعمل Query حسب id معين من قبلنا وتجلب لنا البيانات:

    public LiveData<PagedList<CardEntity>> getAllCardsById(int id) {
        // Configuration for our Paging
        PagedList.Config pagedListConfig = (new PagedList.Config.Builder())
                .setEnablePlaceholders(true)
                .setPrefetchDistance(10)
                .setPageSize(20)
                .build();

        LiveData<PagedList<CardEntity>> cardsById = (new LivePagedListBuilder(mCardDao.getCardsByParentId(id), pagedListConfig)).build();

        return cardsById;
    }

تعقيب:

  • انشئنا عنصر pagedListConfig من PagedList.Config تقوم وظيفته على تخصيص الـ Paging كحجم العناصر المراد سحبها وعرضها في كل صفحة وماشبهه ذلك.
  • الخيار setEnablePlaceholders يسمح لك باستخدام placeholder (مايراه المستخدم) قبل تحميل البيانات بشكل كلي.
  • setPrefetchDistance يسمح  لنا بتحميل الصفحات مسبقاً.
  • setPageSize حجم الصفحات (اي كم item يجب ان تتكون منها الصفحة الواحدة).
  • ثم انشئنا عنصر cardsById من LiveData يغلف قائمة من نوع PageList (لاحظ بالدرس السابقه كانت فقط من نوع List).
  • نقوم بعمل init للـ cardsById وذلك باستخدام Builder وهو عباره عن LivePagedListBuilder ويتطلب تزويدة بـ DataSource.Factory (هنا هي تأتي من الداله getCardsByParentId الموجودة في كلاس الـ CardDao) و ملف Config الذي عملناه اعلاه.
  • اما الـ DataSource.Factory فقد عملناه سابقاً عندما خصصنا CardDao في الدرس الرابع: تهيئة الـ DAO لإستخدام الـ Paging.
  • لاحظ ايضاً هنا نريد ارجاع عناصر من الـ CardEntity حسب id معين لذلك استخدمنا الدالة: mCardDao.getCardsByParentId(id).

 

ونقوم بكتابة دوال التعامل مع البيانات الاخرى ومعالجتهم كـ insert و update و delete. ملاحظة مهمة هنا الـ Repository سيقوم بعمل Delegate الى Dao وايضاً سيقوم بتشغيل هذه الدوال في الخلفية باستخدام Executor (سابقاً كنا نستخدم AsyncTask) والا سوف يتعطل التطبيق اذا قمنا بتشغيل هذه الدوال مباشرة في الـ UI Thread:

    public void insert(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.insertCard(cardEntity);
            }
        });
    }

    public void update(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.updateCard(cardEntity);
            }
        });
    }

    public void delete(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.deleteCard(cardEntity);
            }
        });
    }

    public void deleteAll() {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.deleteAll();
            }
        });
    }

 

لتصبح الكلاس الكاملة على النحو التالي:

package com.mzdhr.flashcards.repository;

import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.arch.paging.LivePagedListBuilder;
import android.arch.paging.PagedList;

import com.mzdhr.flashcards.AppExecutors;
import com.mzdhr.flashcards.database.AppDatabase;
import com.mzdhr.flashcards.database.entity.CardEntity;
import com.mzdhr.flashcards.database.dao.CardDao;

public class CardRepository {
    private static CardRepository sInstance;
    private final CardDao mCardDao;

    private CardRepository(Application application) {
        AppDatabase db = AppDatabase.getInstance(application);
        mCardDao = db.cardDao();
    }

    public static CardRepository getInstance(Application application) {
        if (sInstance == null) {
            synchronized (CardRepository.class) {
                if (sInstance == null) {
                    sInstance = new CardRepository(application);
                }
            }
        }
        return sInstance;
    }


    public LiveData<PagedList<CardEntity>> getAllCardsById(int id) {
        // Configuration for our Paging
        PagedList.Config pagedListConfig = (new PagedList.Config.Builder())
                .setEnablePlaceholders(true)
                .setPrefetchDistance(10)
                .setPageSize(20)
                .build();

        LiveData<PagedList<CardEntity>> cardsById = (new LivePagedListBuilder(mCardDao.getCardsByParentId(id), pagedListConfig)).build();

        return cardsById;
    }

    public void insert(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.insertCard(cardEntity);
            }
        });
    }

    public void update(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.updateCard(cardEntity);
            }
        });
    }

    public void delete(final CardEntity cardEntity) {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.deleteCard(cardEntity);
            }
        });
    }

    public void deleteAll() {
        AppExecutors.getInstance().diskIO().execute(new Runnable() {
            @Override
            public void run() {
                mCardDao.deleteAll();
            }
        });
    }

}

 

كان هذا بالنسبة لتحميل البيانات بشكل offline من الـ Room. واما اذا اردنا تحميل البيانات من الانترنت باستخدام مكتبة Retrofit مع الـ Paging فستكون مقاله منفصله في المستقبل باذن الله.

 

نهاية الدرس

فضلاً اذا اعجبك الدرس لاتنسى الضغظ على زر اعجبني ولنشر الفائدة قم بمشاركته مع من تحب. ولاتنسى تتبع الدرس حتى تطلع على التغييرات والتحديثات المتعلقه به مستقبلاً. وكذلك الامر بالنسبة للدورة من تتبع و اعجاب ومشاركة حتى يصلك جديد الدروس المتعلقه بها.

 

المصادر:

التعليقات (4)

Ali Mohamed Radwan:

 

ايه المشكله هنا 

LiveData<PagedList<CardEntity>> cardsById = (new LivePagedListBuilder(mCardDao.getCardsByParentId(id), pagedListConfig)).build();

Mohammad Laif:

صعب معرفة الخطئ بدون الرسالة! تأكد من الـ import او من الدالة getCardsByParentId في ملف الـ CardDao ماذا تقوم بإرجاعه.

Mina Mikhail:

السلام عليكم اخى العزيز

 

انا سعيد جدا بهذه الدورة الممتازة.

كنت اريد ان اعرف متى ستقوم بعمل شرح كامل لاستخدام Paging Library مع بيانات من Api باستخدام Retrofit مع MVVM

Mohammad Laif:

وعليكم السلام

شكراً على ابداء رأيك واعجابك للدورة.

بالنسبة لإستخدام الـ Paging و الـ API كالـ Retrofit المسأله فقط تغليف الشفرة المسؤلة عن الاستعلام بداخل الـ Repository في دالة ما. تلك الدالة اما تقوم بالإستعلام (عندما يريد المستخدم ذلك او بشكل موقوت) واعطاء الـ ViewModel النتيجه وبدورها تعطيها للمستخدم. او تقوم بالاستعلام وتخزين النتيجه في قاعدة البيانات ثم تعطي المستخدم النتيجة من قاعدة البيانات. يوجد العديد من الطرق في الانترنت لها. في النهاية بعد فهم وتطبيق هذه الدورة على برنامج او برنامجين سيكون الوضوع سهل لعمل او اظافة اي جزئية لها.

وبالنسبة للتحديث او شرحات تتعلق بخصوص الـ MVVM اعتقد انها ستكون بلغة الكوتلن في المستقبل.

لايوجد لديك حساب في عالم البرمجة؟

تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !