वेन हम उस setHasFixedSize(true)पर सेट RecyclerViewकरते हैं इसका मतलब है कि पुनर्नवीनीकरण का आकार तय हो गया है और एडेप्टर सामग्री से प्रभावित नहीं है। और इस मामले onLayoutमें रिसाइकलर पर नहीं बुलाया जाता है जब हम एडेप्टर के डेटा को अपडेट करते हैं (लेकिन एक अपवाद है)।
आइए उदाहरण के लिए चलते हैं:
RecyclerViewएक है RecyclerViewDataObserver( इस फ़ाइल में खोजने डिफ़ॉल्ट implemntation कई तरीके के साथ), मुख्य रूप से महत्वपूर्ण है:
void triggerUpdateProcessor() {
if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
} else {
mAdapterUpdateDuringMeasure = true;
requestLayout();
}
}
अगर हम सेट इस विधि कहा जाता है setHasFixedSize(true)के माध्यम से और एक एडाप्टर के डेटा को अद्यतन: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved। इस मामले में रिसाइकलर के लिए कोई कॉल नहीं है onLayout, लेकिन requestLayoutचिल्ड को अपडेट करने के लिए कॉल है ।
लेकिन अगर हम setHasFixedSize(true)एक एडॉप्टर के डेटा को सेट और अपडेट करते हैं, notifyItemChangedतो onChangeरिसाइकलर के डिफॉल्ट में RecyclerViewDataObserverकॉल होता है और कोई कॉल नहीं होता है triggerUpdateProcessor। इस मामले में recycler onLayoutकहा जाता है जब भी हम सेट setHasFixedSize trueया false।
// no calls to triggerUpdateProcessor
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
// calls to triggerUpdateProcessor
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
triggerUpdateProcessor();
}
}
अपने आप से कैसे जांचें:
कस्टम बनाएँ RecyclerViewऔर ओवरराइड करें:
override fun requestLayout() {
Log.d("CustomRecycler", "requestLayout is called")
super.requestLayout()
}
override fun invalidate() {
Log.d("CustomRecycler", "invalidate is called")
super.invalidate()
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
Log.d("CustomRecycler", "onLayout is called")
super.onLayout(changed, l, t, r, b)
}
match_parent(Xml में) पुनर्नवीनीकरण आकार सेट करें । एडेप्टर के डेटा का उपयोग करके replaceDataऔर सेट करने के replaceOne साथ setHasFixedSize(true)और फिर अपडेट करने का प्रयास करें false।
// onLayout is called every time
fun replaceAll(data: List<String>) {
dataSet.clear()
dataSet.addAll(data)
this.notifyDataSetChanged()
}
// onLayout is called only for setHasFixedSize(false)
fun replaceOne(data: List<String>) {
dataSet.removeAt(0)
dataSet.addAll(0, data[0])
this.notifyItemChanged(0)
}
और अपना लॉग चेक करें।
मेरा लॉग:
// for replaceAll
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onMeasure is called
D/CustomRecycler: onLayout
D/CustomRecycler: requestLayout is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
// for replaceOne
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
संक्षेप:
यदि हम setHasFixedSize(true)कॉल करने के अलावा किसी अन्य तरीके से पर्यवेक्षक को सूचित करने के साथ एडॉप्टर के डेटा को सेट और अपडेट करते हैं notifyDataSetChanged, तो आपके पास कुछ पूर्णता है, क्योंकि रिसाइकलर onLayoutविधि के लिए कोई कॉल नहीं है ।