Wen set setHasFixedSize(true)
üzerinde RecyclerView
en recycler boyutu sabittir ve adaptör içerikleriyle etkilenmemesini yollarla. Ve bu durumda onLayout
(ama bir istisna vardır) biz adaptrer verilerini güncelleme yaptığınızda recycler çağrılmaz.
Örneğe geçelim:
RecyclerView
Bir sahiptir RecyclerViewDataObserver
( bu dosyadaki bulmak varsayılan implemntation çeşitli yöntemler ile), ana önemlidir:
void triggerUpdateProcessor() {
if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
} else {
mAdapterUpdateDuringMeasure = true;
requestLayout();
}
}
Ayarlayacağımız Bu yöntem denir setHasFixedSize(true)
üzerinden bir adaptörünün veri ve güncelleyin: notifyItemRangeChanged, notifyItemRangeInserted, notifyItemRangeRemoved or notifyItemRangeMoved
. Bu durumda geri dönüştürücüye çağrı yapılmaz onLayout
, ancak alt requestLayout
öğelerin güncellenmesi için çağrılar yapılır .
Ayarlayacağımız Ama setHasFixedSize(true)
üzerinden bir adaptörünün veri ve güncellemek notifyItemChanged
ardından çağrı var onChange
Recycler en temerrüt RecyclerViewDataObserver
ve hiçbir aramalar triggerUpdateProcessor
. Bu durumda, geri dönüşüm cihazı onLayout
her ayarladığımızda çağrılır setHasFixedSize
true
veya 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();
}
}
Kendiniz nasıl kontrol edersiniz:
Özel oluştur RecyclerView
ve geçersiz kıl:
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)
}
Geri dönüşümcü boyutunu match_parent
(xml cinsinden) olarak ayarlayın. replaceData
Ve replaceOne
öğelerini setHasFixedSize(true)
ve tuşlarını kullanarak bağdaştırıcı verilerini güncellemeye çalışın 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)
}
Ve günlüğünüzü kontrol edin.
Günlüğüm:
// 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
Özetlemek:
setHasFixedSize(true)
Bağdaştırıcının verilerini bir gözlemciyi çağırmaktan başka bir şekilde bilgilendirerek ayarlar ve güncellersek notifyDataSetChanged
, o zaman bir performansınız olur, çünkü geri dönüşüm onLayout
yöntemine çağrı yoktur .