Wen เราตั้งsetHasFixedSize(true)
อยู่บนRecyclerView
หมายถึงว่าขนาดของรีไซเคิลได้รับการแก้ไขและไม่ได้รับผลกระทบจากเนื้อหาอะแดปเตอร์ และในกรณีนี้onLayout
จะไม่ถูกเรียกใช้กับผู้รีไซเคิลเมื่อเราอัปเดตข้อมูลของอะแดปเตอร์ (แต่มีข้อยกเว้น)
ไปที่ตัวอย่าง:
RecyclerView
มีRecyclerViewDataObserver
( ค้นหาการปรับใช้เริ่มต้นในไฟล์นี้ ) ด้วยวิธีการต่างๆที่สำคัญคือ:
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
ในกรณีนี้รีไซเคิลonLayout
เรียกว่าเมื่อใดก็ตามที่เราตั้งหรือsetHasFixedSize
true
false
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
processDataSetCompletelyChanged(true);
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
@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
มี seting แล้วsetHasFixedSize(true)
false
fun replaceAll(data: List<String>) {
dataSet.clear()
dataSet.addAll(data)
this.notifyDataSetChanged()
}
fun replaceOne(data: List<String>) {
dataSet.removeAt(0)
dataSet.addAll(0, data[0])
this.notifyItemChanged(0)
}
และตรวจสอบบันทึกของคุณ
บันทึกของฉัน:
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
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
D/CustomRecycler: requestLayout is called
D/CustomRecycler: onDraw is called
สรุป:
หากเราตั้งค่าsetHasFixedSize(true)
และอัปเดตข้อมูลของอแด็ปเตอร์โดยแจ้งผู้สังเกตการณ์ด้วยวิธีอื่นที่ไม่ใช่การโทรแสดงnotifyDataSetChanged
ว่าคุณมีประสิทธิภาพเนื่องจากไม่มีการเรียกใช้onLayout
เมธอดรีไซเคิล