طَبِّقْهاتعلّم المبدأ، وطبّقه بيدكمقرر 251 · برمجة الأجهزة الذكية
الدرس 23 · الوحدة 11: تحسين أداء التطبيقات وتقليل البطء

قياس الأداء وتقليل البطء

اكتشف البطء بالقياس وعالجه بالأدوات الصحيحة. ⏱ نحو 40 دقيقة.

بعد هذا الدرس ستستطيع أن:
  • تعدّد أسباب البطء الشائعة وعلاجها.
  • تعرض قوائم كبيرة بكفاءة بـ FlatList.
  • تقيس الأداء (عدّ الرسمات) قبل التحسين.

١البطء عدوّ التجربة

الأجهزة المحمولة أضعف من الحواسيب، وبطء الواجهة (تلعثم التمرير، تأخّر اللمس) يطرد المستخدمين. الناتج الرابع للمقرر يطلب قياس الأداء وتحسينه. أسباب البطء الشائعة:

السببالأثرالعلاج
رسم قائمةٍ ضخمة كاملةذاكرة وبطءFlatList (نافذة مرئيّة)
عملٌ ثقيل في كل رسمتجمّدuseMemo (الدرس 24)
إعادة رسمٍ لا لزوم لهااستهلاكReact.memo (الدرس 24)
صورٌ ضخمةبطء تحميلأحجامٌ مناسبة وتخزين مؤقت

٢قائمةٌ كبيرة بكفاءة

FlatList لا يرسم إلّا المرئيّ. هذه قائمةٌ من 200 عنصرٍ تبقى سلسةً لأنها لا تُرسم كاملة:

import { View, Text, FlatList, StyleSheet } from 'react-native'; const DATA = Array.from({ length: 200 }, (_, i) => ({ id: String(i), n: i + 1 })); export default function App() {  return (    <View style={{ height: 240 }}>      <Text style={styles.h}>200 عنصرًا — مرئيُّها فقط يُرسَم</Text>      <FlatList        data={DATA}        keyExtractor={(it) => it.id}        initialNumToRender={10}        renderItem={({ item }) => (          <Text style={styles.row}>الصفّ رقم {item.n}</Text>        )}      />    </View>  );} const styles = StyleSheet.create({  h: { fontWeight: 'bold', padding: 10, color: '#E8820C' },  row: { padding: 12, borderBottomWidth: 1, borderColor: '#eee' },});

initialNumToRender يحدّد كم عنصرًا يُرسم أولًا. مرّر القائمة: العناصر تُنشأ عند الحاجة لا دفعةً واحدة.

٣قياس بسيط: عدّ الرسمات

«ما لا يُقاس لا يُحسَّن». طريقةٌ بسيطة: عدّاد رسماتٍ بـ useRef يطبع في Console كم مرّةً أُعيد رسم المكوّن. افتح Console وراقب:

import { useState, useRef } from 'react';import { View, Text, Pressable, StyleSheet } from 'react-native'; export default function App() {  const [n, setN] = useState(0);  const renders = useRef(0);  renders.current += 1;  console.log('عدد مرّات الرسم:', renders.current);   return (    <View style={styles.box}>      <Text style={styles.t}>القيمة: {n}</Text>      <Text style={styles.r}>رُسِم {renders.current} مرّة</Text>      <Pressable style={styles.btn} onPress={() => setN(n + 1)}>        <Text style={styles.bt}>زيادة</Text>      </Pressable>    </View>  );} const styles = StyleSheet.create({  box: { padding: 24, alignItems: 'center' },  t: { fontSize: 24, fontWeight: 'bold' },  r: { color: '#888', marginTop: 4 },  btn: { backgroundColor: '#E8820C', padding: 10, borderRadius: 8, marginTop: 12 },  bt: { color: 'white' },});

كل ضغطةٍ تزيد العدّاد والرسمات. في الدرس القادم نقلّل الرسمات غير الضروريّة بـ memo.

توقّع وتحقّق

لماذا FlatList أسرع لقائمةٍ طويلة؟

قاعدة التحسين:

initialNumToRender يحدّد:

عدّاد الرسمات نحفظه بـ:

الخلاصة

تحدٍّ برمجي: قائمة كبيرة سلسة

متوسط

اعرض 50 عنصرًا بـ FlatList.

المطلوب:
  • أنشئ مصفوفةً من 50 عنصرًا.
  • اعرضها بـ FlatList مع keyExtractor.
  • <Text testID="head"> يعرض العدد 50.
👀 اعرض الناتج المطلوب (وجرّبه)
✓ التحقق الآلي من حلّك:
  • الكود يعمل بلا أخطاء في Console
  • العنوان يعرض 50
  • استُخدم FlatList
  • أُنشئت 50 عنصرًا

💡 تلميح 1
Array.from({{ length: 50 }}, …) ينشئ المصفوفة.
💡 تلميح 2
FlatList يرسم المرئيّ فقط.

حاول بنفسك أولًا؛ للمسألة أكثر من حلّ صحيح.

import { View, Text, FlatList, StyleSheet } from 'react-native'; const DATA = Array.from({ length: 50 }, (_, i) => ({ id: String(i), n: i + 1 })); export default function App() {  return (    <View style={{ height: 240 }}>      <Text testID="head" style={styles.h}>العناصر: {DATA.length}</Text>      <FlatList        data={DATA}        keyExtractor={(it) => it.id}        renderItem={({ item }) => <Text style={styles.row}>عنصر {item.n}</Text>}      />    </View>  );} const styles = StyleSheet.create({  h: { fontWeight: 'bold', padding: 10, color: '#E8820C' },  row: { padding: 10, borderBottomWidth: 1, borderColor: '#eee' },});
انتقل إلى تقييم الدرساختيار من متعدد، وصح وخطأ، وأكمل الفراغ، وتتبّع الناتج.ابدأ التقييم ←

📝 معلم؟ أرسل ملاحظة للمؤلف عن هذا الدرس