पेजिंग लाइब्रेरी, पेज किए गए डेटा के लोड करने के अनुरोधों की स्थिति को ट्रैक करती है और
इसे LoadState
क्लास की मदद से किया गया है.
आपका ऐप्लिकेशन, लिसनर को
PagingDataAdapter
से
मौजूदा स्थिति के बारे में जानकारी पाएं और उसके हिसाब से यूज़र इंटरफ़ेस (यूआई) अपडेट करें. ये
स्थितियों को अडैप्टर से लिया जाता है, क्योंकि वे यूज़र इंटरफ़ेस (यूआई) के साथ सिंक होती हैं.
इसका मतलब है कि पेज लोड हो जाने के बाद, लिसनर को अपडेट मिलते हैं
यूज़र इंटरफ़ेस (यूआई) पर लागू किया गया.
हर एक के लिए अलग LoadState
सिग्नल दिया जाता है
LoadType
और डेटा सोर्स का टाइप
(PagingSource
या
RemoteMediator
). कॉन्टेंट बनाने
CombinedLoadStates
लिसनर से मिला ऑब्जेक्ट, लोड होने की स्थिति के बारे में जानकारी देता है
इन सभी सिग्नलों से पता चलता है. आप इस विस्तृत जानकारी का उपयोग
उपयोगकर्ता के लिए सही तरह के लोडिंग इंडिकेटर.
राज्यों के नाम लोड हो रहे हैं
पेजिंग लाइब्रेरी, यूज़र इंटरफ़ेस (यूआई) में इस्तेमाल की जाने वाली लोडिंग स्थिति को
LoadState
ऑब्जेक्ट. LoadState
ऑब्जेक्ट तीन में से एक रूप लेता है. यह इस पर निर्भर करता है
लोड होने की मौजूदा स्थिति:
- अगर लोड करने की कोई कार्रवाई चालू नहीं है और कोई गड़बड़ी नहीं है, तो
LoadState
एकLoadState.NotLoading
ऑब्जेक्ट है. इस सब-क्लास में ये भी शामिल हैं:endOfPaginationReached
प्रॉपर्टी, जिससे पता चलता है कि पेज नंबर खत्म हुआ है या नहीं. - अगर लोड करने की कोई कार्रवाई चालू है, तो
LoadState
एकLoadState.Loading
ऑब्जेक्ट है. - अगर कोई गड़बड़ी होती है, तो
LoadState
LoadState.Error
ऑब्जेक्ट.
यूज़र इंटरफ़ेस (यूआई) में LoadState
का इस्तेमाल करने के दो तरीके हैं: लिसनर का इस्तेमाल करना या
विशेष सूची अडैप्टर, जो पेज लोड होने की स्थिति को सीधे
RecyclerView
सूची.
लिसनर की मदद से, कॉन्टेंट लोड होने की स्थिति को ऐक्सेस करें
अपने यूज़र इंटरफ़ेस (यूआई) में सामान्य इस्तेमाल के लिए, लोड होने की स्थिति जानने के लिए,
loadStateFlow
स्ट्रीम या
addLoadStateListener()
आपके PagingDataAdapter
के ज़रिए उपलब्ध कराया गया तरीका है. इन तरीकों से, आपको
एक CombinedLoadStates
ऑब्जेक्ट, जिसमें LoadState
के बारे में जानकारी शामिल है
व्यवहार की जानकारी शामिल है.
नीचे दिए गए उदाहरण में, PagingDataAdapter
अलग यूज़र इंटरफ़ेस (यूआई) दिखाता है
रीफ़्रेश लोड की मौजूदा स्थिति के आधार पर कॉम्पोनेंट:
// Activities can use lifecycleScope directly, but Fragments should instead use
// viewLifecycleOwner.lifecycleScope.
lifecycleScope.launch {
pagingAdapter.loadStateFlow.collectLatest { loadStates ->
progressBar.isVisible = loadStates.refresh is LoadState.Loading
retry.isVisible = loadState.refresh !is LoadState.Loading
errorMsg.isVisible = loadState.refresh is LoadState.Error
}
}
pagingAdapter.addLoadStateListener(loadStates -> {
progressBar.setVisibility(loadStates.refresh instanceof LoadState.Loading
? View.VISIBLE : View.GONE);
retry.setVisibility(loadStates.refresh instanceof LoadState.Loading
? View.GONE : View.VISIBLE);
errorMsg.setVisibility(loadStates.refresh instanceof LoadState.Error
? View.VISIBLE : View.GONE);
});
pagingAdapter.addLoadStateListener(loadStates -> {
progressBar.setVisibility(loadStates.refresh instanceof LoadState.Loading
? View.VISIBLE : View.GONE);
retry.setVisibility(loadStates.refresh instanceof LoadState.Loading
? View.GONE : View.VISIBLE);
errorMsg.setVisibility(loadStates.refresh instanceof LoadState.Error
? View.VISIBLE : View.GONE);
});
CombinedLoadStates
के बारे में ज़्यादा जानकारी के लिए, अतिरिक्त लोडिंग पेज ऐक्सेस करें
राज्य की जानकारी.
अडैप्टर की मदद से, पेज लोड होने की स्थिति के बारे में बताएं
पेजिंग लाइब्रेरी से एक और लिस्ट अडैप्टर मिलता है, जिसे
LoadStateAdapter
इसका मकसद पेज पर लोड होने की स्थिति को सीधे पेज की गई सूची में दिखाना है
डेटा शामिल है. यह अडैप्टर, सूची की मौजूदा लोड स्थिति को ऐक्सेस करने की सुविधा देता है,
के पास ऐसे कस्टम व्यू होल्डर को पास किया जा सकता है जो जानकारी दिखाता है.
सबसे पहले, एक व्यू होल्डर क्लास बनाएं जिसमें लोड होने और गड़बड़ी के बारे में जानकारी मौजूद हो
दृश्य आपकी स्क्रीन पर दिखाई देंगे. ऐसा bind()
फ़ंक्शन बनाएं जो LoadState
को
पैरामीटर. इस फ़ंक्शन को लोड के हिसाब से, 'किसको दिखे' सेटिंग को टॉगल करना चाहिए
स्थिति पैरामीटर:
class LoadStateViewHolder(
parent: ViewGroup,
retry: () -> Unit
) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.load_state_item, parent, false)
) {
private val binding = LoadStateItemBinding.bind(itemView)
private val progressBar: ProgressBar = binding.progressBar
private val errorMsg: TextView = binding.errorMsg
private val retry: Button = binding.retryButton
.also {
it.setOnClickListener { retry() }
}
fun bind(loadState: LoadState) {
if (loadState is LoadState.Error) {
errorMsg.text = loadState.error.localizedMessage
}
progressBar.isVisible = loadState is LoadState.Loading
retry.isVisible = loadState is LoadState.Error
errorMsg.isVisible = loadState is LoadState.Error
}
}
class LoadStateViewHolder extends RecyclerView.ViewHolder {
private ProgressBar mProgressBar;
private TextView mErrorMsg;
private Button mRetry;
LoadStateViewHolder(
@NonNull ViewGroup parent,
@NonNull View.OnClickListener retryCallback) {
super(LayoutInflater.from(parent.getContext())
.inflate(R.layout.load_state_item, parent, false));
LoadStateItemBinding binding = LoadStateItemBinding.bind(itemView);
mProgressBar = binding.progressBar;
mErrorMsg = binding.errorMsg;
mRetry = binding.retryButton;
}
public void bind(LoadState loadState) {
if (loadState instanceof LoadState.Error) {
LoadState.Error loadStateError = (LoadState.Error) loadState;
mErrorMsg.setText(loadStateError.getError().getLocalizedMessage());
}
mProgressBar.setVisibility(loadState instanceof LoadState.Loading
? View.VISIBLE : View.GONE);
mRetry.setVisibility(loadState instanceof LoadState.Error
? View.VISIBLE : View.GONE);
mErrorMsg.setVisibility(loadState instanceof LoadState.Error
? View.VISIBLE : View.GONE);
}
}
class LoadStateViewHolder extends RecyclerView.ViewHolder {
private ProgressBar mProgressBar;
private TextView mErrorMsg;
private Button mRetry;
LoadStateViewHolder(
@NonNull ViewGroup parent,
@NonNull View.OnClickListener retryCallback) {
super(LayoutInflater.from(parent.getContext())
.inflate(R.layout.load_state_item, parent, false));
LoadStateItemBinding binding = LoadStateItemBinding.bind(itemView);
mProgressBar = binding.progressBar;
mErrorMsg = binding.errorMsg;
mRetry = binding.retryButton;
}
public void bind(LoadState loadState) {
if (loadState instanceof LoadState.Error) {
LoadState.Error loadStateError = (LoadState.Error) loadState;
mErrorMsg.setText(loadStateError.getError().getLocalizedMessage());
}
mProgressBar.setVisibility(loadState instanceof LoadState.Loading
? View.VISIBLE : View.GONE);
mRetry.setVisibility(loadState instanceof LoadState.Error
? View.VISIBLE : View.GONE);
mErrorMsg.setVisibility(loadState instanceof LoadState.Error
? View.VISIBLE : View.GONE);
}
}
इसके बाद, LoadStateAdapter
को लागू करने वाली एक क्लास बनाएं और
onCreateViewHolder()
और
onBindViewHolder()
तरीकों का इस्तेमाल करना होगा. ये तरीके आपके कस्टम व्यू होल्डर का इंस्टेंस बनाते हैं और बाइंड करते हैं
लोड होने की स्थिति के बारे में ज़्यादा जानें.
// Adapter that displays a loading spinner when
// state is LoadState.Loading, and an error message and retry
// button when state is LoadState.Error.
class ExampleLoadStateAdapter(
private val retry: () -> Unit
) : LoadStateAdapter<LoadStateViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
loadState: LoadState
) = LoadStateViewHolder(parent, retry)
override fun onBindViewHolder(
holder: LoadStateViewHolder,
loadState: LoadState
) = holder.bind(loadState)
}
// Adapter that displays a loading spinner when
// state is LoadState.Loading, and an error message and retry
// button when state is LoadState.Error.
class ExampleLoadStateAdapter extends LoadStateAdapter<LoadStateViewHolder> {
private View.OnClickListener mRetryCallback;
ExampleLoadStateAdapter(View.OnClickListener retryCallback) {
mRetryCallback = retryCallback;
}
@NotNull
@Override
public LoadStateViewHolder onCreateViewHolder(@NotNull ViewGroup parent,
@NotNull LoadState loadState) {
return new LoadStateViewHolder(parent, mRetryCallback);
}
@Override
public void onBindViewHolder(@NotNull LoadStateViewHolder holder,
@NotNull LoadState loadState) {
holder.bind(loadState);
}
}
// Adapter that displays a loading spinner when
// state is LoadState.Loading, and an error message and retry
// button when state is LoadState.Error.
class ExampleLoadStateAdapter extends LoadStateAdapter<LoadStateViewHolder> {
private View.OnClickListener mRetryCallback;
ExampleLoadStateAdapter(View.OnClickListener retryCallback) {
mRetryCallback = retryCallback;
}
@NotNull
@Override
public LoadStateViewHolder onCreateViewHolder(@NotNull ViewGroup parent,
@NotNull LoadState loadState) {
return new LoadStateViewHolder(parent, mRetryCallback);
}
@Override
public void onBindViewHolder(@NotNull LoadStateViewHolder holder,
@NotNull LoadState loadState) {
holder.bind(loadState);
}
}
पेज लोड होने की स्थिति को हेडर या फ़ुटर के रूप में दिखाएं
हेडर और फ़ुटर में लोड होने की स्थिति दिखाने के लिए,
withLoadStateHeaderAndFooter()
आपके PagingDataAdapter
ऑब्जेक्ट से तरीका:
pagingAdapter
.withLoadStateHeaderAndFooter(
header = ExampleLoadStateAdapter(adapter::retry),
footer = ExampleLoadStateAdapter(adapter::retry)
)
pagingAdapter
.withLoadStateHeaderAndFooter(
new ExampleLoadStateAdapter(pagingAdapter::retry),
new ExampleLoadStateAdapter(pagingAdapter::retry));
pagingAdapter
.withLoadStateHeaderAndFooter(
new ExampleLoadStateAdapter(pagingAdapter::retry),
new ExampleLoadStateAdapter(pagingAdapter::retry));
इसके बजाय, आप कॉल कर सकते हैं
withLoadStateHeader()
या
withLoadStateFooter()
यदि आप चाहते हैं कि RecyclerView
सूची लोड होने की स्थिति केवल
हेडर या सिर्फ़ फ़ुटर में.
लोड होने की स्थिति के बारे में ज़्यादा जानकारी ऐक्सेस करना
PagingDataAdapter
का CombinedLoadStates
ऑब्जेक्ट इन चीज़ों की जानकारी देता है
आपके PagingSource
को लागू करने के लिए और साथ ही आपके
RemoteMediator
लागू करने की सुविधा, अगर पहले से मौजूद हो.
सुविधा के लिए,
refresh
append
, और
prepend
प्रॉपर्टी को CombinedLoadStates
से इकट्ठा करने के लिए, LoadState
ऑब्जेक्ट को ऐक्सेस किया जा सकता है
लोड होने का सही तरीका चुनें. आम तौर पर ये प्रॉपर्टी, लोड होने की इस स्थिति से
अगर पहले से मौजूद है, तो RemoteMediator
लागू करना; नहीं तो, उनमें
लागू करने से PagingSource
की उचित लोड स्थिति होगी. ज़्यादा जानकारी के लिए
इस्तेमाल किए जा सकने वाले लॉजिक के बारे में जानकारी पाने के लिए,
CombinedLoadStates
.
lifecycleScope.launch {
pagingAdapter.loadStateFlow.collectLatest { loadStates ->
// Observe refresh load state from RemoteMediator if present, or
// from PagingSource otherwise.
refreshLoadState: LoadState = loadStates.refresh
// Observe prepend load state from RemoteMediator if present, or
// from PagingSource otherwise.
prependLoadState: LoadState = loadStates.prepend
// Observe append load state from RemoteMediator if present, or
// from PagingSource otherwise.
appendLoadState: LoadState = loadStates.append
}
}
pagingAdapter.addLoadStateListener(loadStates -> {
// Observe refresh load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState refreshLoadState = loadStates.refresh;
// Observe prepend load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState prependLoadState = loadStates.prepend;
// Observe append load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState appendLoadState = loadStates.append;
});
pagingAdapter.addLoadStateListener(loadStates -> {
// Observe refresh load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState refreshLoadState = loadStates.refresh;
// Observe prepend load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState prependLoadState = loadStates.prepend;
// Observe append load state from RemoteMediator if present, or
// from PagingSource otherwise.
LoadState appendLoadState = loadStates.append;
});
हालांकि, यह याद रखना ज़रूरी है कि सिर्फ़ PagingSource
लोड होने की स्थितियां
इसकी गारंटी है कि ये यूज़र इंटरफ़ेस (यूआई) अपडेट के साथ सिंक होते रहेंगे. क्योंकि refresh
,
append
और prepend
प्रॉपर्टी, लोड होने की स्थिति
PagingSource
या RemoteMediator
के लिए, उनके होने की कोई गारंटी नहीं है
यूज़र इंटरफ़ेस (यूआई) अपडेट के साथ सिंक्रोनस होता है. इसकी वजह से, यूज़र इंटरफ़ेस (यूआई) में समस्याएं हो सकती हैं, जिनमें लोडिंग दिख रही हो
ताकि यूज़र इंटरफ़ेस (यूआई) में कोई भी नया डेटा जोड़े जाने से पहले उसे पूरा कर लिया जाए.
इस वजह से, सुविधा ऐक्सेसर, लोड दिखाने के लिए सही तरीके से काम करते हैं
फ़ाइल होती है, लेकिन अन्य उपयोग के मामलों में आपको
लोड होने की स्थिति को खास तौर पर PagingSource
से ऐक्सेस करें या
RemoteMediator
. CombinedLoadStates
यह देता है
source
और
mediator
प्रॉपर्टी सेट अप की जा सकती हैं. ये प्रॉपर्टी
LoadStates
ऑब्जेक्ट जो
इसमें PagingSource
या RemoteMediator
के लिए LoadState
ऑब्जेक्ट हैं
क्रमश:
lifecycleScope.launch {
pagingAdapter.loadStateFlow.collectLatest { loadStates ->
// Directly access the RemoteMediator refresh load state.
mediatorRefreshLoadState: LoadState? = loadStates.mediator.refresh
// Directly access the RemoteMediator append load state.
mediatorAppendLoadState: LoadState? = loadStates.mediator.append
// Directly access the RemoteMediator prepend load state.
mediatorPrependLoadState: LoadState? = loadStates.mediator.prepend
// Directly access the PagingSource refresh load state.
sourceRefreshLoadState: LoadState = loadStates.source.refresh
// Directly access the PagingSource append load state.
sourceAppendLoadState: LoadState = loadStates.source.append
// Directly access the PagingSource prepend load state.
sourcePrependLoadState: LoadState = loadStates.source.prepend
}
}
pagingAdapter.addLoadStateListener(loadStates -> {
// Directly access the RemoteMediator refresh load state.
LoadState mediatorRefreshLoadState = loadStates.mediator.refresh;
// Directly access the RemoteMediator append load state.
LoadState mediatorAppendLoadState = loadStates.mediator.append;
// Directly access the RemoteMediator prepend load state.
LoadState mediatorPrependLoadState = loadStates.mediator.prepend;
// Directly access the PagingSource refresh load state.
LoadState sourceRefreshLoadState = loadStates.source.refresh;
// Directly access the PagingSource append load state.
LoadState sourceAppendLoadState = loadStates.source.append;
// Directly access the PagingSource prepend load state.
LoadState sourcePrependLoadState = loadStates.source.prepend;
});
pagingAdapter.addLoadStateListener(loadStates -> {
// Directly access the RemoteMediator refresh load state.
LoadState mediatorRefreshLoadState = loadStates.mediator.refresh;
// Directly access the RemoteMediator append load state.
LoadState mediatorAppendLoadState = loadStates.mediator.append;
// Directly access the RemoteMediator prepend load state.
LoadState mediatorPrependLoadState = loadStates.mediator.prepend;
// Directly access the PagingSource refresh load state.
LoadState sourceRefreshLoadState = loadStates.source.refresh;
// Directly access the PagingSource append load state.
LoadState sourceAppendLoadState = loadStates.source.append;
// Directly access the PagingSource prepend load state.
LoadState sourcePrependLoadState = loadStates.source.prepend;
});
LoadState पर चेन ऑपरेटर
क्योंकि CombinedLoadStates
ऑब्जेक्ट, इसमें किए गए सभी बदलावों का ऐक्सेस देता है
लोड स्थिति, लोड स्थिति स्ट्रीम
इवेंट. इससे यह पक्का होता है कि आप अपने यूज़र इंटरफ़ेस (यूआई) को सही समय पर अपडेट करें, ताकि
स्टटर और गैर-ज़रूरी यूज़र इंटरफ़ेस (यूआई) अपडेट.
उदाहरण के लिए, मान लें कि आप एक खाली दृश्य दिखाना चाहते हैं, लेकिन
शुरुआती डेटा लोड पूरा होता है. इस्तेमाल के इस उदाहरण में, आपको यह पुष्टि करनी होगी कि
रीफ़्रेश लोड हो गया है, इसके बाद NotLoading
की स्थिति से इसकी पुष्टि होने का इंतज़ार करें
रीफ़्रेश पूरा हो गया. आपको एक सिग्नल को छोड़कर, बाकी सभी सिग्नल को फ़िल्टर करना होगा
आपको इनकी ज़रूरत होगी:
lifecycleScope.launchWhenCreated {
adapter.loadStateFlow
// Only emit when REFRESH LoadState for RemoteMediator changes.
.distinctUntilChangedBy { it.refresh }
// Only react to cases where REFRESH completes, such as NotLoading.
.filter { it.refresh is LoadState.NotLoading }
// Scroll to top is synchronous with UI updates, even if remote load was
// triggered.
.collect { binding.list.scrollToPosition(0) }
}
PublishSubject<CombinedLoadStates> subject = PublishSubject.create();
Disposable disposable =
subject.distinctUntilChanged(CombinedLoadStates::getRefresh)
.filter(
combinedLoadStates -> combinedLoadStates.getRefresh() instanceof LoadState.NotLoading)
.subscribe(combinedLoadStates -> binding.list.scrollToPosition(0));
pagingAdapter.addLoadStateListener(loadStates -> {
subject.onNext(loadStates);
});
LiveData<CombinedLoadStates> liveData = new MutableLiveData<>();
LiveData<LoadState> refreshLiveData =
Transformations.map(liveData, CombinedLoadStates::getRefresh);
LiveData<LoadState> distinctLiveData =
Transformations.distinctUntilChanged(refreshLiveData);
distinctLiveData.observeForever(loadState -> {
if (loadState instanceof LoadState.NotLoading) {
binding.list.scrollToPosition(0);
}
});
यह उदाहरण रीफ़्रेश लोड स्थिति के अपडेट होने तक इंतज़ार करता है, लेकिन यह केवल ट्रिगर होता है
जब राज्य NotLoading
हो. इससे यह पक्का होता है कि रिमोट रीफ़्रेश
यूज़र इंटरफ़ेस (यूआई) के अपडेट होने से पहले ही पूरा किया जा सकता है.
स्ट्रीम एपीआई के लिए, यह काम किया जा सकता है. आपका ऐप्लिकेशन, लोड होने की जानकारी तय कर सकता है उन इवेंट को ट्रिगर करता है जिनकी उसे ज़रूरत होती है. साथ ही, ज़रूरी शर्तें पूरी होने पर नए डेटा को हैंडल करता है.
फ़िलहाल कोई सुझाव नहीं है.
अपने Google खाते में साइन इन करने की कोशिश करें.