Android Academy · पाठ

PagingSource और Pager

परिभाषित करें कि पेज कैसे लोड किए जाएँ।

पाठ 2, कुल 4 में से13 चरण

PagingSource और Pager, CoddyKit पर Android Academy का एक निःशुल्क पाठ है। यह 4 में से 2वाँ पाठ है। इस अध्ययन पथ के 3 तक कोई भी पाठ पूरा पढ़ना निःशुल्क है — इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ व्यावहारिक अभ्यास भी उपलब्ध कराता है। यह Android Academy सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। Android Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

पेज लोड होने का तरीका निर्धारित करना

नेटवर्क API से पेज लोड करने के लिए आप एक PagingSource लिखते हैं। यह Paging 3 के दो प्रश्नों का उत्तर देता है:

  • दिए गए की के लिए पेज कैसे लोड करना है?
  • यदि उपयोगकर्ता सूची को रीफ़्रेश करे, तो कहाँ से फिर शुरू करना चाहिए?

इसके बाद आप इसे एक Pager में लपेटते हैं, जो इसे Flow<PagingData> में बदल देता है।

PagingSource के प्रकार पैरामीटर

PagingSource<Key, Value> दो प्रकार पैरामीटर लेता है:

  • Key - किसी पेज की पहचान करता है। पेज-नंबर API के लिए यह Int और कर्सर API के लिए String टोकन होता है।
  • Value - आइटम का प्रकार, जैसे Article।
import androidx.paging.PagingSource
import androidx.paging.PagingState

class ArticlePagingSource(
    private val api: ArticleApi
) : PagingSource<Int, Article>() {
    // implement load() and getRefreshKey()
}

load() लागू करना

load() एक suspend फ़ंक्शन है। यह params.key (लाए जाने वाले पेज) प्राप्त करता है और एक LoadResult लौटाता है।

सफलता पर आप आइटम के साथ पिछली और अगली की वाला LoadResult.Page लौटाते हैं। किसी की के लिए null का अर्थ है कि उस दिशा में कोई पेज नहीं है।

override suspend fun load(
    params: LoadParams<Int>
): LoadResult<Int, Article> {
    val page = params.key ?: 1   // first load has a null key
    return try {
        val response = api.getArticles(page = page, size = params.loadSize)
        LoadResult.Page(
            data = response.items,
            prevKey = if (page == 1) null else page - 1,
            nextKey = if (response.items.isEmpty()) null else page + 1
        )
    } catch (e: Exception) {
        LoadResult.Error(e)
    }
}

prevKey और nextKey क्यों महत्वपूर्ण हैं

उपयोगकर्ता के नीचे स्क्रॉल करने पर Paging आगे लोड करने के लिए nextKey और पीछे लोड करने के लिए prevKey का उपयोग करता है। यह सूची के बीच से शुरू करने पर उपयोगी होता है।

nextKey के लिए null लौटाने पर Paging समझता है कि और पेज नहीं हैं, इसलिए अनुरोध करना रोक देता है। इसे भूलने पर खाली अनुरोध अनंत बार हो सकते हैं।

// Stop forward paging when the server returns an empty page
nextKey = if (response.items.isEmpty()) null else page + 1

// Stop backward paging at the first page
prevKey = if (page == 1) null else page - 1

getRefreshKey() लागू करना

जब सूची रीफ़्रेश होती है (पुल-टू-रीफ़्रेश या अमान्य होने पर), तो Paging को यह जानना होता है कि उपयोगकर्ता को लगभग उसी स्थान पर रखने के लिए कौन-सा पेज फिर से लोड करना है।

getRefreshKey() वर्तमान anchorPosition—दृश्य क्षेत्र के सबसे निकट आइटम—का उपयोग करके उपयुक्त की चुनता है।

override fun getRefreshKey(state: PagingState<Int, Article>): Int? {
    return state.anchorPosition?.let { anchor ->
        val closestPage = state.closestPageToPosition(anchor)
        closestPage?.prevKey?.plus(1)
            ?: closestPage?.nextKey?.minus(1)
    }
}

त्रुटियों को सही ढंग से संभालना

नेटवर्क कॉल को try/catch में लपेटें और विफलता पर LoadResult.Error(e) लौटाएँ। Paging इसे UI में LoadState.Error के रूप में उपलब्ध कराता है, जिससे आप पुनः प्रयास बटन दिखा सकते हैं।

किसी अपवाद को load() से बाहर न निकलने दें—उसे पकड़कर LoadResult.Error में बदल दें।

return try {
    val response = api.getArticles(page = page, size = params.loadSize)
    LoadResult.Page(
        data = response.items,
        prevKey = if (page == 1) null else page - 1,
        nextKey = if (response.items.isEmpty()) null else page + 1
    )
} catch (e: IOException) {        // no network
    LoadResult.Error(e)
} catch (e: HttpException) {       // non-2xx response
    LoadResult.Error(e)
}

Pager बनाना

एक Pager आपके PagingConfig को उस फ़ैक्टरी से जोड़ता है जो नया PagingSource बनाती है। इसकी .flow प्रॉपर्टी एक Flow<PagingData> होती है, जिसे UI कलेक्ट करता है।

फ़ैक्टरी लैम्ब्डा को हर बार एक नया स्रोत बनाना चाहिए, क्योंकि रीफ़्रेश होने पर Paging स्रोत को अमान्य करके फिर से बनाता है।

import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow

class ArticleRepository(private val api: ArticleApi) {
    fun articleStream(): Flow<PagingData<Article>> = Pager(
        config = PagingConfig(pageSize = 20, prefetchDistance = 5),
        pagingSourceFactory = { ArticlePagingSource(api) }
    ).flow
}

ViewModel के लिए cachedIn

PagingData को कलेक्ट करना केवल एक बार होने वाली प्रक्रिया है; दोबारा कलेक्ट करने पर लोडिंग फिर शुरू हो जाती है। कॉन्फ़िगरेशन में बदलाव के बाद भी इसे बनाए रखने और कई कलेक्टर को डेटा साझा करने देने के लिए, cachedIn की सहायता से फ़्लो को viewModelScope में कैश करें।

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.cachedIn

class ArticleViewModel(
    repo: ArticleRepository
) : ViewModel() {
    val articles = repo.articleStream()
        .cachedIn(viewModelScope)
}

loadSize बनाम pageSize

ध्यान दें कि load() सीधे आपके कॉन्फ़िगर किए गए pageSize को नहीं, बल्कि params.loadSize को पढ़ता है।

पहली लोडिंग पर Paging एक बड़ा प्रारंभिक हिस्सा माँग सकता है (PagingConfig में initialLoadSize द्वारा नियंत्रित, जिसका डिफ़ॉल्ट पेज आकार का 3 गुना होता है)। अपने API को हमेशा params.loadSize दें, ताकि अनुरोध Paging की अपेक्षा के अनुरूप हो।

// Correct: respect the size Paging asks for
val response = api.getArticles(page = page, size = params.loadSize)

// PagingConfig can tune the first load:
PagingConfig(pageSize = 20, initialLoadSize = 40)

कर्सर-आधारित API

हर API पेज नंबर का उपयोग नहीं करता। कुछ API अगले पेज की ओर संकेत करने वाला कर्सर या टोकन लौटाते हैं। तरीका वही रहता है—बस Key प्रकार को String में बदलें और प्रतिक्रिया से मिले टोकन का उपयोग करें।

class CursorArticleSource(
    private val api: ArticleApi
) : PagingSource<String, Article>() {
    override suspend fun load(
        params: LoadParams<String>
    ): LoadResult<String, Article> {
        val cursor = params.key   // null on first load
        return try {
            val res = api.getArticles(cursor = cursor, size = params.loadSize)
            LoadResult.Page(
                data = res.items,
                prevKey = null,            // forward-only cursor
                nextKey = res.nextCursor   // null when exhausted
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<String, Article>) = null
}

सब कुछ एक साथ जोड़ना

अब आपके पास पूरी डेटा परत है: एक PagingSource जो एक पेज लोड करता है, एक Pager जो पेज की स्ट्रीम बनाता है, और एक ViewModel जो फ़्लो को कैश करता है।

UI परत केवल viewModel.articles को कलेक्ट करती है—अगले पाठ में हम इसे Compose LazyColumn के साथ दिखाएँगे।

// Data layer summary
// 1. ArticlePagingSource : PagingSource<Int, Article>
// 2. Pager(config, factory).flow  -> Flow<PagingData<Article>>
// 3. ViewModel: repo.articleStream().cachedIn(viewModelScope)
// UI just collects viewModel.articles

त्वरित जाँच

पेज-नंबर वाले PagingSource में load() से nextKey = null लौटाने का क्या संकेत मिलता है?

पुनरावृत्ति: PagingSource और Pager

आपने पेजिंग के लिए डेटा परत बनाई:

  • PagingSource<Key, Value> load() और getRefreshKey() लागू करता है
  • load() prevKey/nextKey के साथ LoadResult.Page, या LoadResult.Error लौटाता है
  • null की उस दिशा में पेजिंग रोक देती है
  • Pager(config, factory).flow एक Flow<PagingData> तैयार करता है
  • cachedIn(viewModelScope) कॉन्फ़िगरेशन में बदलाव के दौरान डेटा बनाए रखता है

अगला चरण: इस फ़्लो को Compose सूची में दिखाना।

शुरुआत निःशुल्क

एआई शिक्षक के साथ Kotlin सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
36
पाठ
152

अक्सर पूछे जाने वाले प्रश्न

क्या “PagingSource और Pager” पाठ निःशुल्क है?

हाँ — Android Academy अध्ययन पथ के 3 तक कोई भी पाठ, जिसमें “PagingSource और Pager” भी शामिल है, यहाँ वेब पर पूरा पढ़ना निःशुल्क है। इसके बाद CoddyKit PRO हर पाठ अनलॉक करता है, साथ ही अंतर्निर्मित कोड संपादक और चौबीसों घंटे एआई शिक्षक के साथ इंटरैक्टिव अभ्यास भी उपलब्ध कराता है। Android Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“PagingSource और Pager” में मैं क्या सीखूँगा?

परिभाषित करें कि पेज कैसे लोड किए जाएँ। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ Android Academy का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या Android Academy शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर Android Academy शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 2वाँ पाठ है।

“PagingSource और Pager” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस Android Academy पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर Android Academy पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. पेजिंग क्यों
  2. PagingSource और Pager
  3. Compose सूचियों में पेजिंग
  4. RemoteMediator और कैशिंग
← Android Academy पर वापस जाएँ