Flutter / Dart والعناصر والملكية المحلية / الدرس 6
القوائم والهوية والاختيار
اعرض المجموعات عند الحاجة واحفظ هوية العنصر وخزّن الاختيار بمعرّفات مجال مستقرة.
في هذه الصفحة
أهداف الدرس
- افصل موضع الصف عن هوية العنصر
- استخدم البناء الكسول للمجموعات الكبيرة
- امنح الصفوف الشقيقة مفاتيح بهويات مستقرة
افصل موضع الصف عن هوية العنصر
يصف الفهرس موضع العنصر في ترتيب معين، بينما يصف المعرّف المستقر أي عنصر مجال هو. يغيّر الترشيح والفرز والإدراج والحذف المواضع دون تغيير الهويات بالضرورة. إذا خُزّن الاختيار كفهرس 2، فقد يختار إدراج في البداية سجلا آخر بصمت. خزّن معرّف الاختيار واشتق الصف من البيانات الحالية. وقرّر صراحة ماذا يحدث عند غياب المعرّف: إزالة الاختيار أو عرض حالة عنصر مفقود أو حفظ اختيار مقصود عبر الصفحات بحسب عقد المنتج.
استخدم البناء الكسول للمجموعات الكبيرة
يطلب ListView.builder الصفوف حسب حاجة مساحة العرض بدلا من بناء كل الصفوف مسبقا داخل Column. وفّر itemCount عندما يكون معروفا لتحديد نهاية مفهومة. ينبغي لرد البناء اشتقاق الصف من البيانات الحالية وتجنب بدء طلب مستقل كلما طُلب الصف. قد يُعاد إنشاء صف خرج من مساحة العرض لاحقا، لذلك تنتمي حالة المجال الدائمة إلى النموذج لا إلى الصف المختفي وحده. يقلل البناء الكسول بعض التكاليف، لكنه لا يجعل فك صورة مكلفا أو تخطيطا معقدا بلا كلفة.
امنح الصفوف الشقيقة مفاتيح بهويات مستقرة
يستخدم المقتطف الأول ValueKey مبنيا على معرّف كل سجل مصطنع. يخبر المفتاح عملية التوفيق أي وصف شقيق يمثل الصف المنطقي نفسه بعد تغير الترتيب. يوضع المفتاح على العنصر عند حد الأشقاء المتغيرين، لا مدفونا تحت غلاف بلا مفتاح يملك الموضع الفعلي. ليس المفتاح بحثا عاما في قاعدة بيانات ولا يحتاج إلى كشف بيانات خاصة. وتخرق المفاتيح المكررة بين الأشقاء عقد الهوية. وعند إعادة ترتيب صفوف ذات حالة في builder راجع أيضا سلوك findChildIndexCallback الموثق بدلا من افتراض أن المفتاح يعالج كل الحالات.
final records = <({String id, String title})>[
(id: 'book-7', title: 'Maps'),
(id: 'book-9', title: 'Rivers'),
];
Widget rows() => ListView.builder(
itemCount: records.length,
itemBuilder: (context, index) {
final item = records[index];
return ListTile(key: ValueKey(item.id), title: Text(item.title));
},
);
Two keyed rows display Maps and Rivers in the current order.
تحتاج صيغة السجلات إلى Dart SDK متوافق. حُذفت عمدا بيئة Flutter المحيطة ومساحة العرض المحدودة.
استبدل المجموعات تحت مالك واضح
يشتق المقتطف الثاني مجموعة جديدة عند تبديل معرّف. يجعل إنشاء مجموعة جديدة الانتقال واضحا ويمنع تعديل مجموعة مشتركة مع لقطة حالة سابقة. ويسند مالك الواجهة المجموعة المعادة عبر آلية حالته المختارة. يفيد ذلك حين يقارن الاختبار الحالة السابقة واللاحقة، أو يحتفظ مكوّن آخر بلقطة للقراءة. وفي النماذج الأكبر تظل التحديثات الثابتة بحاجة إلى الانتباه للقيم الداخلية. ينسخ الانتشار السطحي عضوية المجموعة لا كل الكائنات المشار إليها، لذا وثّق المواضع التي تسمح بالكائنات القابلة للتعديل.
Set<String> toggle(Set<String> selected, String id) {
final next = <String>{...selected};
if (!next.add(id)) next.remove(id);
return next;
}
void main() {
final before = <String>{'book-7'};
final after = toggle(before, 'book-9');
print(before.length);
print(after.contains('book-9'));
}
1
true
تبقى المجموعة الأصلية بلا تغيير. واستدعاء toggle مرة أخرى للمعرّف نفسه يزيله من النتيجة الجديدة.
مثّل المجموعات الفارغة والمتغيرة بوضوح
تختلف نتيجة الترشيح الفارغة عن التحميل وعن الطلب الفاشل. امنح كل حالة تمثيلا مستقلا لتشرح الواجهة ما حدث وتقترح فعلا مناسبا. وإذا اختفى عنصر مختار فاشتق الاختيار المرئي بأمان بدلا من استعمال فهرس لقائمة متقادمة. وتجنب تعديل القائمة نفسها أثناء قراءة builder لها؛ انشر لقطة متسقة تحت مالك واحد. وأثناء جلب الصفحات ميّز التحميل الأول من تحميل صفحة إضافية حتى لا تختفي الصفوف المفيدة خلف مؤشر يملأ الشاشة.
اختبر الهوية بإعادة ترتيب فعلية
يحرر اختبار هوية مفيد مسودة في صف، ثم يعيد ترتيب المجموعة ويتحقق من بقاء المسودة مع المعرّف نفسه. لا يكشف مجرد ظهور العناوين كلها انتقال الحالة بين الصفوف. اختبر أيضا الإدراج في البداية وحذف الصف المختار ورفض المعرّفات المكررة عند حدود البيانات ونتيجة ترشيح فارغة. وإذا احتوت القائمة عناصر تفاعلية، فتحقق من تسمياتها الدلالية والتركيز بعد الانتقال. تمثل الهوية جزءا من صحة التفاعل، وليست تحسين أداء فقط أو وسيلة لإسكات تشخيص الإطار.
الأخطاء الشائعة وإصلاحها
يقفز الاختيار بعد إدراج صف
- لماذا يحدث؟
- خُزن الموضع المختار بدلا من الهوية المستقرة.
- كيف تصلحه؟
- خزّن معرّف المجال واشتق الصف الحالي.
- كيف تتجنب تكراره؟
- اختبر الإدراج في البداية وترتيب النتائج المرشحة.
يبلغ شقيقان عن مفاتيح مكررة
- لماذا يحدث؟
- المفتاح المختار غير فريد ضمن مجموعة الأشقاء.
- كيف تصلحه؟
- تحقق من المعرّفات واختر هوية العنصر الفعلية.
- كيف تتجنب تكراره؟
- ارفض المدخلات المكررة المعيبة قبل العرض.
تختفي مسودات الصفوف الخارجة عن العرض
- لماذا يحدث؟
- عاشت المسودة الدائمة داخل حالة صف قابلة للإزالة فقط.
- كيف تصلحه؟
- انقل المسودات الدائمة إلى مالك يفهرسها بمعرّفات العناصر.
- كيف تتجنب تكراره؟
- حدّد هل يسمح بخسارة العمل المحلي عند مغادرة مساحة العرض.
اختبر فهمك
1. لماذا لا يكفي ValueKey(index) لصفوف قابلة للتحرير يعاد ترتيبها؟
اعرض الحل المشروح
يحفظ الفهرس هوية الموضع لا هوية عنصر المجال. بعد الفرز قد يمثل الموضع نفسه عنصرا آخر ويحتفظ بالحالة المحلية الخاطئة. استخدم معرّف عنصر مستقرا عند حد الأشقاء واختبر الصف المحرر خلال إعادة الترتيب.
2. يختفي معرّف مختار أثناء التحديث. ماذا ينبغي للنموذج أن يفعل؟
اعرض الحل المشروح
اختر سياسة صريحة. في اختيار صفحة واحدة، قاطع الاختيار مع المعرّفات الحالية واشرح غياب العنصر عند الحاجة. وفي اختيار عابر للصفحات، احتفظ بالمعرّف منفصلا مع فحص التوافر قبل أي أمر. ولا تعِد تفسيره بوصفه العنصر عند الفهرس القديم.
أهم ما تعلمته
- افصل موضع الصف عن هوية العنصر
- اختبر الهوية بإعادة ترتيب فعلية