Route هي فئة مجردة في Flutter تمثل شاشة أو صفحة منفصلة في تاريخ التنقل في Navigator. التطبيقات الملموسة لـ Route — MaterialPageRoute و CupertinoPageRoute و PlatformRoute — تحدد كيفية عرض الشاشة والرسوم المتحركة المستخدمة أثناء الانتقال. على عكس الـ widget العادي، Route لها دورة حياة خاصة بها مع طرق didPush و didPop و didReplace و didChangeNext. وفقًا Flutter API Reference (2026)، تدير كل Route ModalBarrier، وتراعي الميزات الخاصة بالمنصة (التمرير للخلف على iOS) وتضمن عزل الحالة بين الشاشات.
النقاط الرئيسية
Route هي أساس نظام التنقل في Flutter. كل شاشة يراها المستخدم في التطبيق يتم تمثيلها بواسطة كائن Route موجود في مكدس Navigator. Route تجرد الشاشة من كود التحكم: Navigator يضيف ويزيل Route، بينما داخل Route توجد الواجهة التي يراها المستخدم. هذه البنية تفصل المسؤولية بين التنقل والعرض.
على عكس استبدال الـ widget البسيط، Route توفر خدمات غير متاحة للـ widgets العادية: ModalBarrier (تعتيم الخلفية عند فتح حوار)، التحكم في الرسوم المتحركة للدخول والخروج، معالجة زر الرجوع الفعلي على Android والتكامل مع رسوم Hero المتحركة للانتقالات السلسة بين الشاشات.
وفقًا Flutter Cookbook (2026)، Route عنصر رئيسي لرسوم Hero المتحركة: widget Hero على Route واحدة تحرك تلقائيًا الانتقال إلى widget Hero على Route التالية، مما يخلق تأثير عنصر «طائر». هذا ممكن لأن Route تحتفظ بكلتا الشاشتين في الطبقة العلوية أثناء الرسوم المتحركة.
Route هي الأساس لكل من تطبيقات الهاتف البسيطة (عبر Navigator 1.0) والسيناريوهات المعقدة مع الروابط العميقة (Navigator 2.0). في Navigator 2.0، Route تمثل Page التي يحولها RouterDelegate من تكوين المسار. لذلك، فهم Route ضروري للعمل مع أي نظام تنقل في Flutter — بغض النظر عن النهج أو الحزمة المختارة.
Flutter يوفر عدة تطبيقات مدمجة لـ Route، كل منها يكيّف السلوك لمنصة محددة. اختيار النوع الصحيح من Route يؤثر على تجربة المستخدم: رسوم Material المتحركة على Android ورسوم Cupertino المتحركة على iOS تخلق شعور تطبيق «أصلي».
| نوع Route | الرسوم المتحركة | المنصة | الميزات |
|---|---|---|---|
| MaterialPageRoute | انزلاق من الأسفل إلى الأعلى | Android، سطح المكتب | ظل عند الانتقال، معالجة تلقائية لـ SafeArea |
| CupertinoPageRoute | انزلاق من اليمين إلى اليسار | iOS، iPadOS | إيماءة التمرير للخلف، خلفية شفافة أثناء الانتقال |
| PlatformRoute | اختيار تلقائي | جميع المنصات | يختار النوع بناءً على TargetPlatform |
| PageRouteBuilder | مخصصة | جميع المنصات | تحكم كامل في الرسوم المتحركة عبر AnimationController |
MaterialPageRoute هو تطبيق Route الأكثر استخدامًا. يحرك الشاشة الجديدة من الأسفل إلى الأعلى مع ظهور تدريجي. عند الخروج، تتحرك الشاشة من الأعلى إلى الأسفل، عائدة إلى موضعها الأصلي. شريط الأدوات (AppBar) وجسم الشاشة يتحركان بشكل منفصل، مما يخلق تأثيرًا هرميًا.
CupertinoPageRoute يحاكي UINavigationController من iOS. تدخل الشاشة الجديدة من اليمين، لتغطي الشاشة السابقة. الميزة الرئيسية هي دعم إيماءة التمرير للخلف التفاعلية، المُنفذة عبر CupertinoBackGestureDetector. تتم معالجة هذه الإيماءة حتى أثناء الحركة، مما يوفر سلوكًا طبيعيًا مألوفًا لمستخدمي iPhone.
Route لها دورة حياة خاصة بها، تختلف عن دورة حياة StatefulWidget العادي. فهم هذه الدورة ضروري للتهيئة الصحيحة للبيانات والاشتراكات في التدفقات وتحرير الموارد عند إغلاق الشاشة.
تتكون دورة حياة Route من أربع مراحل رئيسية. الانتقال — يتم إنشاء Route وتحريكها عند الدخول (يتم استدعاء didPush). نشط — يتم عرض Route بالكامل والتفاعل مع المستخدم. غير نشط — Route أخرى تغطي الحالية (حوار، لوحة سفلية)، لكن Route تبقى في المكدس. مهمل — تتم إزالة Route من المكدس وتدميرها، يتم استدعاء didPop و dispose.
يمكن تجاوز طرق دورة حياة Route في تطبيق مخصص. على سبيل المثال، يتم استدعاء didPop عند إزالة Route من المكدس — هنا يمكن حفظ بيانات المسودة. يتم استدعاء didChangeNext عندما تتغير Route التالية في المكدس — مفيد لتحديث واجهة المستخدم عند تغيير تاريخ التنقل.
وفقًا Flutter API Route.didPop (2026)، من المهم عدم الخلط بين دورة حياة Route ودورة حياة State داخل Route. StatefulWidget داخل Route له initState و dispose الخاصين به، واللذان يتم استدعاؤهما أثناء مرحلتي الانتقال والتدمير على التوالي. Route تعيش أطول من State الداخلي — Route تبقى في الطبقة العلوية حتى عندما تكون widgetsها مخفية مؤقتًا بواسطة Route أخرى.
Route توفر آليات لنقل البيانات سواء عند الدخول (عند الإنشاء) أو عند الخروج (عند الانتهاء). نقل البيانات بشكل صحيح عبر Route يلغي الحاجة للمتغيرات العامة و InheritedWidget، مما يجعل التنقل آمنًا من حيث النوع وقابلًا للتنبؤ.
لنقل البيانات إلى شاشة جديدة، استخدم مُنشئ الـ widget المستقبل أو الوسيط arguments في Navigator.pushNamed. داخل Route، البيانات متاحة عبر RouteSettings.arguments، المخزنة في كائن Route. هذا النهج يعمل مع جميع أنواع Route — MaterialPageRoute و CupertinoPageRoute والتطبيقات المخصصة.
لإرجاع البيانات، استخدم الوسيط الثاني لـ Navigator.pop(context, result). Navigator.push يعيد Future
عند استدعاء Navigator.push مباشرة مع MaterialPageRoute، يتم تمرير البيانات عبر مُنشئ الشاشة الهدف. لا يتم استخدام MethodChannel — هذا تفاعل Dart خالص. هذا النهج مفضل للنقل الآمن للأنواع للكائنات المعقدة.
لننظر إلى مثال لإنشاء Route مخصص مع رسوم متحركة خاصة به ونقل بيانات. PageRouteBuilder يسمح بتعريف رسوم متحركة للدخول والخروج مع تحكم كامل في منحنى الحركة ومدتها.
// Route مخصص مع رسوم متحركة انزلاقية
Navigator.push(context, PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) {
return DetailPage(productId: '42');
},
transitionsBuilder: (context, animation, secondaryAnimation, child) {
const begin = Offset(0.0, 0.3);
const end = Offset.zero;
final tween = Tween(begin: begin, end: end);
final offsetAnimation = animation.drive(tween);
return SlideTransition(position: offsetAnimation, child: child);
},
transitionDuration: const Duration(milliseconds: 400),
));
// إرجاع البيانات من الشاشة
ElevatedButton(
onPressed: () => Navigator.of(context).pop({'selected': true, 'id': '42'}),
child: const Text('تحديد'),
);
// الحصول على النتيجة في شاشة الاستدعاء
final result = await Navigator.push(context, MaterialPageRoute(
builder: (context) => const SelectionPage(),
));
if (result != null) {
print(':${result[ المحدد'selected']}');
}
في المثال، PageRouteBuilder يعرف رسومًا متحركة مخصصة للانزلاق من الأسفل مع شفافية. transitionDuration يحدد سرعة الحركة. يوضح الكود أيضًا تمرير النتيجة: شاشة التفاصيل تعيد Map مع اختيار المستخدم، والشاشة المستدعية تستقبل هذه البيانات عبر Future من push. Route تضمن عزلًا كاملًا: المسودات على شاشة التفاصيل لا تؤثر على حالة القائمة.
الأسئلة الشائعة
Route هو كائن يدير شاشة على مستوى التنقل: يخزن الرسوم المتحركة و ModalBarrier ودورة الحياة. Widget هو وصف لجزء من الواجهة. Route تحتوي على Widget بداخلها، ولكنها توفر أيضًا خدمات (طبقة التراكب، رسوم Hero المتحركة) غير متاحة للـ widgets العادية. Route واحدة يمكن أن تحتوي على تسلسل هرمي معقد من widgets بأي عمق.
استخدم PageRouteBuilder مع معاملات pageBuilder (بناء الشاشة) و transitionsBuilder (تعريف الرسوم المتحركة). في transitionsBuilder، تتوفر animation (0.0–1.0) و secondaryAnimation للرسوم المتحركة المتوازية. للتحكم الكامل، أنشئ فئة فرعية من Route وoverride buildPage و createAnimationController و buildTransitions، مما يتيح الوصول إلى AnimationController منخفض المستوى.
لنقل كائنات معقدة، استخدم مُنشئ الشاشة الهدف عند استدعاء Navigator.push مباشرة أو معامل arguments مع pushNamed. تأكد من أن الكائن قابل للتسلسل (Map أو JSON أو فئة مخصصة). للنقل الآمن من حيث النوع في Flutter، استخدم نماذج freezed أو json_serializable التي تضمن إلغاء تسلسل صحيح عند التمرير عبر RouteSettings.
Route.dispose لا يتم استدعاؤها إذا بقيت Route في مكدس Navigator. على سبيل المثال، عند فتح Route جديدة، تنتقل Route القديمة إلى حالة غير نشطة ولكنها لا تُدمر — تبقى في المكدس للعودة السريعة. يتم استدعاء dispose فقط عند إزالة Route من المكدس عبر pop أو pushReplacement أو pushAndRemoveUntil. لتحرير الموارد، استخدم dispose الخاص بـ State داخل Route، وليس dispose الخاص بـ Route نفسها.
استخدم ModalRoute.of(context) للحصول على Route الحالية من BuildContext. الخاصية ModalRoute.isActive تظهر ما إذا كانت Route هي الشاشة المرئية حاليًا. ModalRoute.isCurrent — true إذا كانت Route هي قمة المكدس. لمراقبة تغييرات المكدس، اشترك في مراقبي Navigator عبر RouteAware و RouteObserver، اللذان يبلغان عن تغييرات Route النشطة.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا