داده های صفحه بندی شده را جمع آوری کنید

این راهنما مبتنی بر نمای کلی کتابخانه صفحه‌بندی است و در مورد چگونگی سفارشی‌سازی راه‌حل بارگذاری داده برنامه‌تان برای رفع نیازهای معماری برنامه‌تان بحث می‌کند.

یک لیست قابل مشاهده بسازید

به طور معمول، کد UI شما یک شی LiveData<PagedList> (یا اگر از RxJava2 استفاده می کنید، یک شیء Flowable<PagedList> یا Observable<PagedList> ) را مشاهده می کند که در ViewModel برنامه شما قرار دارد. این شیء قابل مشاهده ارتباطی بین نمایش و محتوای داده های لیست برنامه شما ایجاد می کند.

برای ایجاد یکی از این اشیاء PagedList قابل مشاهده، یک نمونه از DataSource.Factory را به یک شی LivePagedListBuilder یا RxPagedListBuilder ارسال کنید. یک شی DataSource صفحات را برای یک PagedList بارگیری می کند. کلاس کارخانه نمونه های جدیدی از PagedList را در پاسخ به به روز رسانی محتوا، مانند باطل شدن جدول پایگاه داده و به روز رسانی شبکه ایجاد می کند. کتابخانه تداوم اتاق می تواند اشیاء DataSource.Factory را برای شما فراهم کند، یا می توانید خود را بسازید .

قطعه کد زیر نحوه ایجاد یک نمونه جدید از LiveData<PagedList> را در کلاس ViewModel برنامه خود با استفاده از قابلیت‌های Room's DataSource.Factory -building نشان می‌دهد:

کنسرت دائو

کاتلین

@Dao
interface ConcertDao {
    // The Int type parameter tells Room to use a PositionalDataSource
    // object, with position-based loading under the hood.
    @Query("SELECT * FROM concerts ORDER BY date DESC")
    fun concertsByDate(): DataSource.Factory<Int, Concert>
}

جاوا

@Dao
public interface ConcertDao {
    // The Integer type parameter tells Room to use a PositionalDataSource
    // object, with position-based loading under the hood.
    @Query("SELECT * FROM concerts ORDER BY date DESC")
    DataSource.Factory<Integer, Concert> concertsByDate();
}

ConcertViewModel

کاتلین

// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
       concertDao.concertsByDate()

val concertList = myConcertDataSource.toLiveData(pageSize = 50)

جاوا

// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
       concertDao.concertsByDate();

LiveData<PagedList<Concert>> concertList =
        LivePagedListBuilder(myConcertDataSource, /* page size */ 50).build();

پیکربندی صفحه بندی خود را تعریف کنید

برای پیکربندی بیشتر LiveData<PagedList> برای موارد پیشرفته، می‌توانید پیکربندی صفحه‌بندی خود را نیز تعریف کنید. به طور خاص، می توانید ویژگی های زیر را تعریف کنید:

  • اندازه صفحه : تعداد موارد موجود در هر صفحه.
  • فاصله از پیش واکشی : با توجه به آخرین مورد قابل مشاهده در رابط کاربری برنامه، تعداد مواردی فراتر از آخرین موردی که کتابخانه صفحه‌بندی باید از قبل تلاش کند واکشی کند. این مقدار باید چندین برابر بزرگتر از اندازه صفحه باشد.
  • حضور جای‌بان : تعیین می‌کند که آیا UI برای آیتم‌های فهرستی که هنوز بارگیری نشده‌اند، متغیرهایی را نمایش می‌دهد یا خیر. برای بحث در مورد مزایا و معایب استفاده از متغیرهایی، یاد بگیرید که چگونه متغیرهایی را در رابط کاربری خود ارائه کنید .

اگر می‌خواهید کنترل بیشتری روی زمانی که کتابخانه صفحه‌بندی فهرستی را از پایگاه داده برنامه شما بارگیری می‌کند، یک شی Executor سفارشی را به LivePagedListBuilder ارسال کنید، همانطور که در قطعه کد زیر نشان داده شده است:

ConcertViewModel

کاتلین

val myPagingConfig = Config(
        pageSize = 50,
        prefetchDistance = 150,
        enablePlaceholders = true
)

// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
        concertDao.concertsByDate()

val concertList = myConcertDataSource.toLiveData(
        pagingConfig = myPagingConfig,
        fetchExecutor = myExecutor
)

جاوا

PagedList.Config myPagingConfig = new PagedList.Config.Builder()
        .setPageSize(50)
        .setPrefetchDistance(150)
        .setEnablePlaceholders(true)
        .build();

// The Integer type argument corresponds to a PositionalDataSource object.
DataSource.Factory<Integer, Concert> myConcertDataSource =
        concertDao.concertsByDate();

LiveData<PagedList<Concert>> concertList =
        new LivePagedListBuilder<>(myConcertDataSource, myPagingConfig)
            .setFetchExecutor(myExecutor)
            .build();

نوع منبع داده صحیح را انتخاب کنید

مهم است که به منبع داده ای که به بهترین شکل ساختار داده منبع شما را مدیریت می کند وصل شوید:

  • اگر صفحاتی که بارگیری می کنید کلیدهای بعدی/قبلی را جاسازی می کنند، از PageKeyedDataSource استفاده کنید. به عنوان مثال، اگر پست‌های رسانه‌های اجتماعی را از شبکه دریافت می‌کنید، ممکن است لازم باشد یک نشانه nextPage را از یک بار به بار بعدی منتقل کنید.
  • اگر نیاز به استفاده از داده های مورد N برای واکشی مورد N+1 دارید، از ItemKeyedDataSource استفاده کنید. برای مثال، اگر نظرات رشته‌ای را برای یک برنامه گفتگو واکشی می‌کنید، ممکن است لازم باشد شناسه آخرین نظر را برای دریافت محتوای نظر بعدی ارسال کنید.
  • اگر نیاز به واکشی صفحات داده از هر مکانی که در فروشگاه داده خود انتخاب می کنید، از PositionalDataSource استفاده کنید. این کلاس از درخواست مجموعه ای از اقلام داده که از هر مکانی که انتخاب می کنید شروع می شود پشتیبانی می کند. به عنوان مثال، درخواست ممکن است 50 مورد داده را که با مکان 1500 شروع می شوند، برگرداند.

در صورت نامعتبر بودن داده ها اطلاع دهید

هنگام استفاده از کتابخانه صفحه‌بندی، این وظیفه لایه داده است که وقتی جدول یا ردیفی کهنه شده است، سایر لایه‌های برنامه شما را مطلع کند. برای انجام این کار، از کلاس DataSource که برای برنامه خود انتخاب کرده اید، invalidate() را فراخوانی کنید.

منابع داده خود را بسازید

اگر از یک راه حل سفارشی داده محلی استفاده می کنید، یا اگر داده ها را مستقیماً از یک شبکه بارگیری می کنید، می توانید یکی از زیر کلاس های DataSource را پیاده سازی کنید. قطعه کد زیر منبع داده ای را نشان می دهد که از زمان شروع کنسرت مشخص شده است:

کاتلین

class ConcertTimeDataSource() :
        ItemKeyedDataSource<Date, Concert>() {
    override fun getKey(item: Concert) = item.startTime

    override fun loadInitial(
            params: LoadInitialParams<Date>,
            callback: LoadInitialCallback<Concert>) {
        val items = fetchItems(params.requestedInitialKey,
                params.requestedLoadSize)
        callback.onResult(items)
    }

    override fun loadAfter(
            params: LoadParams<Date>,
            callback: LoadCallback<Concert>) {
        val items = fetchItemsAfter(
            date = params.key,
            limit = params.requestedLoadSize)
        callback.onResult(items)
    }
}

جاوا

public class ConcertTimeDataSource
        extends ItemKeyedDataSource<Date, Concert> {
    @NonNull
    @Override
    public Date getKey(@NonNull Concert item) {
        return item.getStartTime();
    }

    @Override
    public void loadInitial(@NonNull LoadInitialParams<Date> params,
            @NonNull LoadInitialCallback<Concert> callback) {
        List<Concert> items =
            fetchItems(params.key, params.requestedLoadSize);
        callback.onResult(items);
    }

    @Override
    public void loadAfter(@NonNull LoadParams<Date> params,
            @NonNull LoadCallback<Concert> callback) {
        List<Concert> items =
            fetchItemsAfter(params.key, params.requestedLoadSize);
        callback.onResult(items);
    }

سپس می‌توانید این داده‌های سفارشی‌شده را با ایجاد یک زیرکلاس مشخص از DataSource.Factory در اشیاء PagedList بارگیری کنید. قطعه کد زیر نحوه تولید نمونه های جدید از منبع داده سفارشی تعریف شده در قطعه کد قبلی را نشان می دهد:

کاتلین

class ConcertTimeDataSourceFactory :
        DataSource.Factory<Date, Concert>() {
    val sourceLiveData = MutableLiveData<ConcertTimeDataSource>()
    var latestSource: ConcertDataSource?
    override fun create(): DataSource<Date, Concert> {
        latestSource = ConcertTimeDataSource()
        sourceLiveData.postValue(latestSource)
        return latestSource
    }
}

جاوا

public class ConcertTimeDataSourceFactory
        extends DataSource.Factory<Date, Concert> {
    private MutableLiveData<ConcertTimeDataSource> sourceLiveData =
            new MutableLiveData<>();

    private ConcertDataSource latestSource;

    @Override
    public DataSource<Date, Concert> create() {
        latestSource = new ConcertTimeDataSource();
        sourceLiveData.postValue(latestSource);
        return latestSource;
    }
}

نحوه عملکرد به روز رسانی محتوا را در نظر بگیرید

همانطور که اشیاء PagedList قابل مشاهده را می سازید، نحوه عملکرد به روز رسانی محتوا را در نظر بگیرید. اگر داده‌ها را مستقیماً از پایگاه داده اتاق بارگیری می‌کنید، به‌روزرسانی‌ها به‌طور خودکار به رابط کاربری برنامه شما منتقل می‌شوند.

هنگام استفاده از یک API شبکه صفحه‌دار، معمولاً یک تعامل با کاربر دارید، مانند «تند کشیدن برای تازه کردن»، به عنوان سیگنالی برای بی‌اعتبار کردن DataSource که اخیراً استفاده کرده‌اید عمل می‌کند. سپس یک نمونه جدید از آن منبع داده را درخواست می کنید. این قطعه کد زیر این رفتار را نشان می دهد:

کاتلین

class ConcertActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        concertTimeViewModel.refreshState.observe(this, Observer {
            // Shows one possible way of triggering a refresh operation.
            swipeRefreshLayout.isRefreshing =
                    it == MyNetworkState.LOADING
        })
        swipeRefreshLayout.setOnRefreshListener {
            concertTimeViewModel.invalidateDataSource()
        }
    }
}

class ConcertTimeViewModel(firstConcertStartTime: Date) : ViewModel() {
    val dataSourceFactory = ConcertTimeDataSourceFactory(firstConcertStartTime)
    val concertList: LiveData<PagedList<Concert>> =
            dataSourceFactory.toLiveData(
                pageSize = 50,
                fetchExecutor = myExecutor
            )

    fun invalidateDataSource() =
            dataSourceFactory.sourceLiveData.value?.invalidate()
}

جاوا

public class ConcertActivity extends AppCompatActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        // ...
        viewModel.getRefreshState()
                .observe(this, new Observer<NetworkState>() {
            // Shows one possible way of triggering a refresh operation.
            @Override
            public void onChanged(@Nullable MyNetworkState networkState) {
                swipeRefreshLayout.isRefreshing =
                        networkState == MyNetworkState.LOADING;
            }
        };

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshListener() {
            @Override
            public void onRefresh() {
                viewModel.invalidateDataSource();
            }
        });
    }
}

public class ConcertTimeViewModel extends ViewModel {
    private LiveData<PagedList<Concert>> concertList;
    private DataSource<Date, Concert> mostRecentDataSource;

    public ConcertTimeViewModel(Date firstConcertStartTime) {
        ConcertTimeDataSourceFactory dataSourceFactory =
                new ConcertTimeDataSourceFactory(firstConcertStartTime);
        mostRecentDataSource = dataSourceFactory.create();
        concertList = new LivePagedListBuilder<>(dataSourceFactory, 50)
                .setFetchExecutor(myExecutor)
                .build();
    }

    public void invalidateDataSource() {
        mostRecentDataSource.invalidate();
    }
}

ارائه نقشه داده ها

کتابخانه صفحه‌بندی از تبدیل‌های مبتنی بر آیتم و مبتنی بر صفحه آیتم‌های بارگیری‌شده توسط DataSource پشتیبانی می‌کند.

در قطعه کد زیر، ترکیبی از نام کنسرت و تاریخ کنسرت به یک رشته منفرد که هم نام و هم تاریخ را در خود دارد نگاشت می‌شود:

کاتلین

class ConcertViewModel : ViewModel() {
    val concertDescriptions : LiveData<PagedList<String>>
        init {
            val concerts = database.allConcertsFactory()
                    .map { "${it.name} - ${it.date}" }
                    .toLiveData(pageSize = 50)
        }
}

جاوا

public class ConcertViewModel extends ViewModel {
    private LiveData<PagedList<String>> concertDescriptions;

    public ConcertViewModel(MyDatabase database) {
        DataSource.Factory<Integer, Concert> factory =
                database.allConcertsFactory().map(concert ->
                    concert.getName() + "-" + concert.getDate());
        concertDescriptions = new LivePagedListBuilder<>(
            factory, /* page size */ 50).build();
    }
}

این می تواند مفید باشد اگر بخواهید موارد را پس از بارگیری بسته بندی، تبدیل یا آماده کنید. از آنجایی که این کار بر روی مجری واکشی انجام می شود، می توانید کارهای بالقوه گرانی مانند خواندن از روی دیسک یا جستجو در یک پایگاه داده جداگانه انجام دهید.

بازخورد ارائه دهید

نظرات و ایده های خود را از طریق این منابع با ما در میان بگذارید:

ردیاب مشکل
مشکلات را گزارش کنید تا بتوانیم اشکالات را برطرف کنیم.

منابع اضافی

برای کسب اطلاعات بیشتر در مورد کتابخانه صفحه بندی، به منابع زیر مراجعه کنید.

نمونه ها

Codelabs

ویدیوها

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}