ReactNative/optimizing flatlist configuration
تحسين إعداد قائمة مسطحة Flatlist
مصطلحات
- VirtualizedList: وهو المكوّن الكامن وراء
FlatList
(تنفيذ إطار React Native لمفهوم القائمة الافتراضيةVirtual List
). - استهلاك الذاكرة Memory consumption: مقدار المعلومات المخزَّنة في قائمتك ضمن الذاكرة، مما قد يؤدي إلى تعطّل التطبيق.
- الاستجابة Responsiveness: قدرة التطبيق على الاستجابة للتفاعلات، فالاستجابة المنخفضة مثلًا هي عندما تلمس أحد المكوّنات وينتظر هذا المكون قليلًا ليستجيب، بدلًا من الاستجابة الفورية كما هو متوقَّع.
- المناطق الفارغة Blank areas: يمكنك إدخال جزء من قائمتك بمكونات غير مصيَّرة وظاهرة كمنطقة فارغة، عندما يتعذّر على القائمة
VirtualizedList
تصيير render العناصر الخاصة بك بالسرعة الكافية. - إطار العرض Viewport: المنطقة المرئية من المحتوى التي تُصيَّر إلى بكسلات.
- النافذة Window: هي المنطقة التي يجب تحميل العناصر فيها، والتي تكون أكبر بكثير من إطار العرض Viewport.
الخاصيات Props
سنعرض فيما يلي قائمة بالخاصيات التي يمكن أن تساعد في تحسين أداء القائمة FlatList
:
removeClippedSubviews
النوع | القيمة الافتراضية |
---|---|
Boolean | False |
إذا كانت قيمة هذه الخاصية true
، فستُفصَل العروض الموجودة خارج إطار العرض عن هرمية العرض الأصيلة.
الإيجابيات: يعمل ذلك على تقليل الوقت المُستغرَق في الخيط thread الرئيسي، وبالتالي يقلل من مخاطر إسقاط الإطارات، عن طريق استبعاد العروض الموجودة خارج إطار العرض من التصيير الأصيل ورسم عمليات العبور traversals.
السلبيات: يجب أن تدرك أن هذا التنفيذ قد يحتوي على أخطاء، مثل المحتوى المفقود (المُلاحَظ بصورة أساسية على نظام iOS)، خاصةً إذا تنفيذ بأشياء معقدة باستخدام تحويلات و / أو تحديد الموضع المطلق. لاحظ أيضًا أن ذلك لا يوفّر ذاكرةً كبيرة بسبب عدم إلغاء تخصيص deallocated العروض، وإنما فصلها detached فقط.
maxToRenderPerBatch
النوع | القيمة الافتراضية |
---|---|
Number | 10 |
وهي خاصية VirtualizedList
التي يمكن تمريرها عبر قائمة FlatList
. تتحكم هذه الخاصية في مقدار العناصر المُصيَّرة لكل دفعة، وهي القطعة التالية من العناصر المُصيَّرة في كل تمرير scroll.
الإيجابيات: يعني ضبطُ عدد أكبر تقليلَ المناطق الفارغة المرئية عند التمرير (أي يزيد من معدّل التعبئة).
السلبيات: يعني المزيد من العناصر لكل دفعة فتراتٍ أطول لتنفيذ شيفرة JavaScript الذي يحتمل أن يوقف معالجة الأحداث الأخرى -مثل الضغط presses- مما يضر بالاستجابة.
updateCellsBatchingPeriod
النوع | القيمة الافتراضية |
---|---|
Number | 50 |
تعطينا الخاصية maxToRenderPerBatch
مقدار العناصر التي المُصيَّرة لكل دفعة، بينما يعطي إعداد الخاصية updateCellsBatchingPeriod
القائمة VirtualizedList
الخاصة بك التأخيرَ مقدرًا بالميلي ثانية بين عمليات تصيير الدُفعات (أي عدد المرات التي سيصيّر فيها المكون العناصر المعروضة في النوافذ).
الإيجابيات: يمنحك الجمع بين هذه الخاصية مع الخاصية maxToRenderPerBatch
القدرة على تصيير المزيد من العناصر في دفعة أقل تكرارًا على سبيل المثال، أو تصيير عناصر أقل في دفعة أكثر تكرارًا.
السلبيات: قد تتسبب الدُفعات الأقل تكرارًا في وجود مناطق فارغة، وقد تتسبب الدفعات الأكثر تكرارًا في حدوث مشكلات في الاستجابة.
initialNumToRender
النوع | القيمة الافتراضية |
---|---|
Number | 10 |
تمثّل هذه الخاصية المقدار الأولي للعناصر المراد تصييرها.
الإيجابيات: تحديد عدد العناصر التي ستغطي الشاشة لكل جهاز بدقة، وبالتالي يمكن أن يكون هذا تعزيزًا كبيرًا لأداء التصيير الأولي.
السلبيات: قد يؤدي تعيين قيمة منخفضة للخاصية initialNumToRender
إلى ظهور مناطق فارغة، وخاصةً إن كانت صغيرة جدًا بحيث لا تغطي إطار العرض عند التصيير الأولي.
windowSize
النوع | القيمة الافتراضية |
---|---|
Number | 21 |
الرقم الذي نمرّره هو وحدة قياس، حيث يكافئ الرقم 1 ارتفاع إطار العرض viewport. القيمة الافتراضية هي 21 (أي 10 إطارات عرض في الأعلى، و 10 في الأسفل، وواحد بينهما).
الإيجابيات: سينتج عن حجم النافذة windowSize
الأكبر فرصة أقل لرؤية منطقة فارغة أثناء التمرير، بينما سيؤدي حجم النافذة windowSize
الأصغر إلى عدد أقل من العناصر المُحمَّلة في الوقت ذاته، مما يوفّر من الذاكرة.
السلبيات: سيكون لديك استهلاك ذاكرة أكبر بالنسبة لحجم نافذة windowSize
أكبر، بينما سيكون لديك فرصة أكبر لرؤية مناطق فارغة بالنسبة لحجم نافذة windowSize
منخفض.
عناصر القائمة
سنعرض فيما يلي بعض النصائح حول مكونات عناصر القائمة، فهذه العناصر هي أساس قائمتك، لذلك يجب أن تكون سريعة.
استخدام المكونات الأساسية
كلما كانت مكوناتك أكثر تعقيدًا، كلما كان تصييرها أبطأ، لذلك حاول تجنب الكثير من المنطق والتداخل بين عناصر قائمتك. إن أعدَّت استخدام مكون عنصر القائمة كثيرًا في تطبيقك، فأنشئ مكونًا فقط لقوائمك الكبيرة واجعلها تحتوي أقل قدر ممكن من المنطق والتداخل.
استخدم المكونات الخفيفة
كلما كانت مكوناتك أثقل، كلما كان تصييرها أبطأ. تجنّب استخدام الصور الثقيلة (استخدم نسخة مقصوصة أو صورة مصغَّرة لعناصر القائمة، واجعلها أصغر ما يمكن). تحدّث إلى فريق التصميم الخاص بك، واستخدم أقل قدر ممكن من التأثيرات والتفاعلات والمعلومات في قائمتك، ولكن أظهرها في تفاصيل عنصرك.
استخدام التابع shouldComponentUpdate
طبّق تحققًا من تحديث مكوناتك. يطبّق الصنف PureComponent
الخاص بمكتبة React التابع shouldComponentUpdate
بمقارنة ضئيلة. وهذا مكلف لأنه يحتاج إلى فحص جميع خاصياتك. إن أردت أداءً جيدًا على مستوى البت، فأنشئ القواعد الأكثر صرامة لمكونات عناصر القائمة مع فحص العناصر التي يمكن أن تتغير فقط. إذا كانت قائمتك أساسية بما يكفي، فيمكنك استخدام ما يلي:
shouldComponentUpdate() {
return false
}
استخدام الصور المحسَّنة والمخزَّنة مؤقتًا
يمكنك استخدام حزم المجتمع (مثل react-native-fast-image لصاحبها DylanVann) للحصول على صور ذات أداءً افضل. كل صورة في قائمتك هي نسخة من التابع new Image()
. كلما وصلت إلى الخطاف loaded
بصورة أسرع، كلما زادت سرعة تحرير خيط JavaScript مرة أخرى.
استخدام الخاصية getItemLayout
إن كانت جميع مكونات عناصر القائمة لديك لها نفس الارتفاع (أو العرض في قائمة أفقية)، فإن توفير الخاصية getItemLayout يزيل الحاجة إلى القائمة FlatList
لإدارة حسابات التخطيط غير المتزامن، وهذه تقنية تحسين مرغوبة للغاية.
إن كانت مكوناتك ذات حجم ديناميكي وأنت بحاجة أداء أفضل، فاسأل فريق التصميم الخاص بك عن التفكير في إعادة التصميم من أجل الحصول على أداء أفضل.
استخدام المفتاح keyExtractor أو key
يمكنك ضبط المفتاح keyExtractor
للمكوّن FlatList
الخاص بك، حيث تُستخدَم هذه الخاصية للتخزين المؤقت caching وكمفتاح React لتتبّع إعادة ترتيب العناصر. يمكنك أيضًا استخدام خاصيّة المفتاح key
في مكوّن العنصر الخاص بك.
تجنّب الدالة المجهولة في renderItem
انقل الدالة renderItem
إلى خارج دالة التصيير، لذلك لن تعيد إنشاء نفسها في كل استدعاء لدالة التصيير.
renderItem = ({ item }) => (<View key={item.key}><Text>{item.title}</Text></View>);
render(){
// ...
<FlatList
data={items}
renderItem={renderItem}
/>
// ...
}