شارك المقالة

استخدام IndexedStack في Flutter لحفظ عناصر التبويبات مع فهم كلفة البناء والذاكرة وTickerMode وحدود الفهرس والمهام المخفية.

الحفاظ على State لا يعني إيقاف الشجرة

IndexedStack يرسم الطفل المختار ويحتفظ بأطفاله، لكن ذلك لا يمنع build أو الحسابات أو المؤقتات في الفروع المخفية. ليس أسرع دائمًا من PageView أو Navigator؛ افحص حجم الفروع وعددها وحجم صورها. حافظ على هوية children والمفاتيح عندما تتغير القائمة حتى لا تنتقل حالة عنصر إلى تبويب مختلف.

تحكم في النشاط وقيود الفهرس

استخدم TickerMode لإيقاف tickers غير اللازمة، وأوقف الاشتراكات أو الاستعلامات المتكررة وفق سياسة الميزة؛ لا تفترض أن إخفاء العنصر يوقفها. تأكد أن index يقع داخل children، وميّز حفظ حالة تبويب في الذاكرة عن استعادتها بعد إغلاق العملية. اختبر التبديل أثناء تحرير نص ثم حذف تبويب أو تغيير ترتيبه.

حالة اختبار سريعة

اكتب نصًا مختلفًا في كل تبويب ثم عد إليه؛ بقاء النص يختبر حفظ الحالة داخل الشجرة.

خطوات التطبيق والشرح

مشكلة الأداء عند التبديل بين الشاشات؟ IndexedStack يحلها بسهولة

لماذا يفضل المحترفون IndexedStack على Navigator؟

في تطوير واجهات المستخدم باستخدام Flutter، يلعب اختيار الأدوات (Widgets) المناسبة دورًا حيويًا في تحقيق أداء عالٍ وتجربة مستخدم سلسة. واحدة من هذه الأدوات هي IndexedStack، وهي وحدة قوية تُستخدم لإدارة عرض مجموعة من الأبناء (Children) بطريقة فعالة. في هذا المقال، سنستعرض كيفية استخدام IndexedStack في الكود المقدم، وكيفية تحسين الأداء وتوفير تجربة مستخدم أفضل.

ما هو IndexedStack؟

IndexedStack هو ويدجت في Flutter يسمح بعرض واحد فقط من بين عدة أبناء في وقت معين. يتم تحديد الابن الذي سيتم عرضه باستخدام خاصية index. على عكس Stack العادي الذي يقوم بتراكب جميع الأبناء فوق بعضهم البعض، فإن IndexedStack يعرض فقط الابن المحدد بواسطة الفهرس (index) ويحتفظ بحالة جميع الأبناء الأخرى في الذاكرة.

 IndexedStack من اهم مميزات 

أحد أهم مميزات IndexedStack هو أنه يحافظ على حالة جميع الأبناء حتى إذا لم يتم عرضها. على سبيل المثال، إذا كان المستخدم في DashBoardLayout() ثم انتقل إلى OrdersScreen()، فسيتم الاحتفاظ بحالة DashBoardLayout() عند العودة إليها. هذا يجعل الانتقال بين الشاشات سريعًا وسلسًا.

فوائد استخدام IndexedStack في هذا السياق

  • سهولة الإدارة: يمكن إدارة عرض الشاشات المختلفة بسهولة عن طريق تغيير الفهرس فقط.
  • الحفاظ على الحالة: كما ذكرنا سابقًا، يتم الاحتفاظ بحالة كل شاشة حتى عند التبديل بينها.
  • أداء عالٍ: بحسب تكلفة الشجرة والمهام النشطة؛ الاحتفاظ بالشاشات لا يمنع إعادة البناء، فإن الأداء يكون أفضل مقارنة باستخدام أدوات مثل Navigator أو PageView.

استخدام IndexedStack في الكود المقدم يعكس فهمًا جيدًا لأدوات Flutter وإمكاناتها. يوفر IndexedStack طريقة فعالة لإدارة عرض الشاشات المختلفة مع الحفاظ على الحالة والأداء. ومع ذلك، يجب مراعاة التحديات المحتملة مثل استهلاك الذاكرة وإدارة الحالة الديناميكية لضمان تجربة مستخدم مثالية.

مثال حول استخدام IndexedStack في Flutter

في هذا المثال، سنوضح كيفية استخدام IndexedStack لإنشاء تطبيق بسيط يحتوي على ثلاث شاشات رئيسية يتم التبديل بينها باستخدام أزرار التنقل السفلي (BottomNavigationBar).

كيف يعمل التطبيق؟

عند تشغيل التطبيق، يتم عرض الشاشة الأولى (Screen1) لأن _currentIndex يساوي 0.
عند النقر على أيقونة في شريط التنقل السفلي:
يتم تحديث _currentIndex إلى الفهرس المقابل للشاشة المختارة.
يتم إعادة بناء واجهة المستخدم لعرض الشاشة الجديدة باستخدام IndexedStack.
يتم الاحتفاظ بحالة جميع الشاشات في الذاكرة، مما يعني أن أي تغييرات تتم على الشاشات (مثل إدخال بيانات) ستبقى كما هي عند العودة إليها.

مثال الشفرة بعد المراجعة

اقرأ التعليقات ومتطلبات الإعداد قبل النقل إلى مشروعك. أمثلة الواجهات ذات main مستقلة، أما العقود والمقاطع الأصلية وملفات الإعداد فموضح نطاقها داخل المثال.

import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: DemoPage()));
class DemoPage extends StatefulWidget {
 const DemoPage({super.key});
 @override
 State<DemoPage> createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
int _selected=0;

 @override
 Widget build(BuildContext context) => Scaffold(
 appBar: AppBar(title: const Text('Flutter lesson')),
 body: Column(children: [SegmentedButton<int>(segments: const [ButtonSegment(value:0,label:Text('First')),ButtonSegment(value:1,label:Text('Second'))],selected:{_selected},onSelectionChanged:(s)=>setState(()=>_selected=s.single)), Expanded(child: IndexedStack(index:_selected, children: const [TextField(decoration:InputDecoration(labelText:'First draft')), TextField(decoration:InputDecoration(labelText:'Second draft'))]))]));
}

مرجع للتنفيذ

راجع التوثيق الخاص بهذا الموضوع وطابق إعداداته مع إصدار أدوات مشروعك. اختبر السلوك المستهدف وحالة الفشل قبل إدماج المثال في تطبيق منشور.

شاهد أيضًا
مقالات ذات صلة
🚫 مانع الإعلانات مفعل

يجب إيقاف مانع الإعلانات لاستكمال تصفح الموقع