यह दस्तावेज़, पेजिंग लाइब्रेरी की खास जानकारी पर आधारित है. इसमें बताया गया है कि ऐप्लिकेशन के आर्किटेक्चर की ज़रूरतों को पूरा करने के लिए, डेटा लोड करने के समाधान को कैसे पसंद के मुताबिक बनाया जा सकता है.
ऑब्ज़र्व की जा सकने वाली सूची बनाना
आम तौर पर, आपका यूज़र इंटरफ़ेस (यूआई) कोड, LiveData<PagedList> ऑब्जेक्ट को मॉनिटर करता है. अगर RxJava2 का इस्तेमाल किया जा रहा है, तो यह Flowable<PagedList> या Observable<PagedList> ऑब्जेक्ट को मॉनिटर करता है. यह ऑब्जेक्ट, आपके ऐप्लिकेशन के ViewModel में मौजूद होता है.
यह ऑब्ज़र्वेबल ऑब्जेक्ट, प्रज़ेंटेशन और आपके ऐप्लिकेशन के लिस्ट डेटा के कॉन्टेंट के बीच कनेक्शन बनाता है.
इनमें से कोई एक ऑब्ज़र्वेबल PagedList ऑब्जेक्ट बनाने के लिए, DataSource.Factory के इंस्टेंस को LivePagedListBuilder या RxPagedListBuilder ऑब्जेक्ट में पास करें. DataSource ऑब्जेक्ट, किसी एक PagedList के लिए पेज लोड करता है. फ़ैक्ट्री क्लास, कॉन्टेंट के अपडेट के जवाब में PagedList के नए इंस्टेंस बनाती है. जैसे, डेटाबेस टेबल का अमान्य होना और नेटवर्क रीफ़्रेश होना. रूम परसिस्टेंस लाइब्रेरी आपको DataSource.Factory ऑब्जेक्ट उपलब्ध करा सकती है. इसके अलावा, अपना ऑब्जेक्ट खुद भी बनाया जा सकता है.
यहां दिए गए कोड स्निपेट में, Room की DataSource.Factory-बिल्डिंग क्षमताओं का इस्तेमाल करके, आपके ऐप्लिकेशन की ViewModel क्लास में LiveData<PagedList> का नया इंस्टेंस बनाने का तरीका बताया गया है:
ConcertDao
Kotlin
@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>
}
Java
@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
Kotlin
// The Int type argument corresponds to a PositionalDataSource object.
val myConcertDataSource : DataSource.Factory<Int, Concert> =
concertDao.concertsByDate()
val concertList = myConcertDataSource.toLiveData(pageSize = 50)
Java
// 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> को और कॉन्फ़िगर करने के लिए, पेजिंग कॉन्फ़िगरेशन को भी तय किया जा सकता है. खास तौर पर, इन एट्रिब्यूट को तय किया जा सकता है:
- पेज का साइज़: हर पेज पर मौजूद आइटम की संख्या.
- प्रीफ़ेच डिस्टेंस: ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) में दिखने वाले आखिरी आइटम के बाद, ऐसे आइटम की संख्या जिन्हें पेजिंग लाइब्रेरी को पहले से फ़ेच करने की कोशिश करनी चाहिए. यह वैल्यू, पेज के साइज़ से कई गुना ज़्यादा होनी चाहिए.
- प्लेसहोल्डर की मौजूदगी: इससे यह तय होता है कि यूज़र इंटरफ़ेस (यूआई) में, सूची के उन आइटम के लिए प्लेसहोल्डर दिखेंगे या नहीं जो अब तक लोड नहीं हुए हैं. प्लेसहोल्डर इस्तेमाल करने के फ़ायदों और नुकसानों के बारे में जानने के लिए, अपने यूज़र इंटरफ़ेस (यूआई) में प्लेसहोल्डर उपलब्ध कराने का तरीका जानें.
अगर आपको इस बात पर ज़्यादा कंट्रोल चाहिए कि पेजिंग लाइब्रेरी आपके ऐप्लिकेशन के डेटाबेस से सूची कब लोड करे, तो LivePagedListBuilder को कस्टम Executor ऑब्जेक्ट पास करें. इसके बारे में यहां दिए गए कोड स्निपेट में बताया गया है:
ConcertViewModel
Kotlin
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
)
Java
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+1 को फ़ेच करने के लिए, आइटम N के डेटा का इस्तेमाल करना है, तो
ItemKeyedDataSourceका इस्तेमाल करें. उदाहरण के लिए, अगर आपको किसी चर्चा वाले ऐप्लिकेशन के लिए थ्रेड वाली टिप्पणियां फ़ेच करनी हैं, तो आपको अगली टिप्पणी का कॉन्टेंट पाने के लिए, पिछली टिप्पणी का आईडी पास करना पड़ सकता है. - अगर आपको अपने डेटास्टोर में चुनी गई किसी भी जगह से डेटा के पेज फ़ेच करने हैं, तो
PositionalDataSourceका इस्तेमाल करें. इस क्लास की मदद से, डेटा आइटम के सेट का अनुरोध किया जा सकता है. यह सेट, आपकी चुनी गई जगह से शुरू होता है. उदाहरण के लिए, अनुरोध करने पर 1,500वीं जगह से शुरू होने वाले 50 डेटा आइटम मिल सकते हैं.
डेटा अमान्य होने पर सूचना पाना
पेजिंग लाइब्रेरी का इस्तेमाल करते समय, डेटा लेयर को आपके ऐप्लिकेशन की अन्य लेयर को यह सूचना देनी होती है कि कोई टेबल या लाइन पुरानी हो गई है. इसके लिए, अपने ऐप्लिकेशन के लिए चुनी गई DataSource क्लास से invalidate() को कॉल करें.
अपने डेटा सोर्स बनाना
अगर कस्टम लोकल डेटा सलूशन का इस्तेमाल किया जाता है या डेटा को सीधे नेटवर्क से लोड किया जाता है, तो DataSource सबक्लास में से किसी एक को लागू किया जा सकता है. यहां दिए गए कोड स्निपेट में, एक डेटा सोर्स दिखाया गया है. इसे किसी कॉन्सर्ट के शुरू होने के समय के हिसाब से सेट किया गया है:
Kotlin
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)
}
}
Java
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);
}
}
इसके बाद, इस कस्टमाइज़ किए गए डेटा को PagedList ऑब्जेक्ट में लोड किया जा सकता है. इसके लिए, आपको DataSource.Factory का एक कॉन्क्रीट सबक्लास बनाना होगा. यहां दिए गए कोड स्निपेट से पता चलता है कि पिछले कोड स्निपेट में तय किए गए कस्टम डेटा सोर्स के नए इंस्टेंस कैसे जनरेट किए जाते हैं:
Kotlin
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
}
}
Java
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 ऑब्जेक्ट बनाते समय, इस बात का ध्यान रखें कि कॉन्टेंट के अपडेट कैसे काम करते हैं. अगर डेटा को सीधे Room डेटाबेस से लोड किया जा रहा है, तो अपडेट आपके ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) पर अपने-आप पुश हो जाते हैं.
पेज वाले नेटवर्क एपीआई का इस्तेमाल करते समय, आम तौर पर उपयोगकर्ता के साथ इंटरैक्शन होता है. जैसे, "रीफ़्रेश करने के लिए स्वाइप करें". यह उस DataSource को अमान्य करने के सिग्नल के तौर पर काम करता है जिसका आपने हाल ही में इस्तेमाल किया है. इसके बाद, उस डेटा सोर्स के नए इंस्टेंस का अनुरोध किया जाता है. यहां दिए गए कोड स्निपेट से इस व्यवहार के बारे में पता चलता है:
Kotlin
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()
}
Java
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 से लोड किए गए आइटम के आइटम-आधारित और पेज-आधारित ट्रांसफ़ॉर्मेशन के साथ काम करती है.
यहां दिए गए कोड स्निपेट में, कॉन्सर्ट के नाम और तारीख के कॉम्बिनेशन को एक स्ट्रिंग से मैप किया गया है. इस स्ट्रिंग में, कॉन्सर्ट का नाम और तारीख, दोनों शामिल हैं:
Kotlin
class ConcertViewModel : ViewModel() {
val concertDescriptions : LiveData<PagedList<String>>
init {
val concerts = database.allConcertsFactory()
.map { "${it.name} - ${it.date}" }
.toLiveData(pageSize = 50)
}
}
Java
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();
}
}
यह तब काम आ सकता है, जब आपको आइटम लोड होने के बाद उन्हें रैप करना हो, कन्वर्ट करना हो या तैयार करना हो. यह काम फ़ेच एक्ज़ीक्यूटर पर किया जाता है. इसलिए, आपके पास डिस्क से डेटा पढ़ने या किसी अलग डेटाबेस से क्वेरी करने जैसे महंगे काम करने का विकल्प होता है.
सुझाव/राय दें या शिकायत करें
इन संसाधनों के ज़रिए, अपने सुझाव, शिकायत या राय और आइडिया हमारे साथ शेयर करें:
- समस्या को ट्रैक करने वाला टूल

- समस्याओं की शिकायत करें, ताकि हम बग ठीक कर सकें.
अन्य संसाधन
पेजिंग लाइब्रेरी के बारे में ज़्यादा जानने के लिए, यहां दिए गए संसाधन देखें.
सैंपल
कोडलैब
वीडियो
- Android Jetpack: manage infinite lists with RecyclerView and Paging (Google I/O '18)
- Android Jetpack: Paging
आपके लिए सुझाव
- ध्यान दें: JavaScript बंद होने पर, लिंक टेक्स्ट दिखता है
- Paging 3 पर माइग्रेट करना
- Paging 2 लाइब्रेरी के बारे में खास जानकारी
- पेज वाली सूचियां दिखाना