Route — ما هو، أنواع وإنشاء المسارات في Flutter

المؤلف: IT Sectr نُشر: 2026-07-02 وقت القراءة: 8 دق

Route هي فئة مجردة في Flutter تمثل شاشة أو صفحة منفصلة في تاريخ التنقل في Navigator. التطبيقات الملموسة لـ Route — MaterialPageRoute و CupertinoPageRoute و PlatformRoute — تحدد كيفية عرض الشاشة والرسوم المتحركة المستخدمة أثناء الانتقال. على عكس الـ widget العادي، Route لها دورة حياة خاصة بها مع طرق didPush و didPop و didReplace و didChangeNext. وفقًا Flutter API Reference (2026)، تدير كل Route ModalBarrier، وتراعي الميزات الخاصة بالمنصة (التمرير للخلف على iOS) وتضمن عزل الحالة بين الشاشات.

النقاط الرئيسية

  • Route — فئة شاشة مجردة في Flutter بدورة حياة خاصة بها (didPush, didPop, didReplace, didChangeNext)
  • MaterialPageRoute — التطبيق القياسي لـ Route مع رسوم متحركة Material (انزلاق من الأسفل) لنظام Android وسطح المكتب
  • CupertinoPageRoute — تطبيق Route مع رسوم متحركة لنظام iOS (انزلاق من اليمين + إيماءة التمرير للخلف) لـ iPhone و iPad
  • دورة الحياة — تمر Route بمراحل: انتقال، نشط، غير نشط ومهمل
  • نقل البيانات — تقبل Route الوسائط عبر المُنشئ وتعيد النتيجة عبر Future عند الانتهاء

ما هو Route في Flutter

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 كلبنة بناء للتنقل

Route هي الأساس لكل من تطبيقات الهاتف البسيطة (عبر Navigator 1.0) والسيناريوهات المعقدة مع الروابط العميقة (Navigator 2.0). في Navigator 2.0، Route تمثل Page التي يحولها RouterDelegate من تكوين المسار. لذلك، فهم Route ضروري للعمل مع أي نظام تنقل في Flutter — بغض النظر عن النهج أو الحزمة المختارة.

أنواع Route: MaterialPageRoute و CupertinoPageRoute

Flutter يوفر عدة تطبيقات مدمجة لـ Route، كل منها يكيّف السلوك لمنصة محددة. اختيار النوع الصحيح من Route يؤثر على تجربة المستخدم: رسوم Material المتحركة على Android ورسوم Cupertino المتحركة على iOS تخلق شعور تطبيق «أصلي».

نوع Routeالرسوم المتحركةالمنصةالميزات
MaterialPageRouteانزلاق من الأسفل إلى الأعلىAndroid، سطح المكتبظل عند الانتقال، معالجة تلقائية لـ SafeArea
CupertinoPageRouteانزلاق من اليمين إلى اليسارiOS، iPadOSإيماءة التمرير للخلف، خلفية شفافة أثناء الانتقال
PlatformRouteاختيار تلقائيجميع المنصاتيختار النوع بناءً على TargetPlatform
PageRouteBuilderمخصصةجميع المنصاتتحكم كامل في الرسوم المتحركة عبر AnimationController

MaterialPageRoute: المعيار لنظام Android

MaterialPageRoute هو تطبيق Route الأكثر استخدامًا. يحرك الشاشة الجديدة من الأسفل إلى الأعلى مع ظهور تدريجي. عند الخروج، تتحرك الشاشة من الأعلى إلى الأسفل، عائدة إلى موضعها الأصلي. شريط الأدوات (AppBar) وجسم الشاشة يتحركان بشكل منفصل، مما يخلق تأثيرًا هرميًا.

CupertinoPageRoute: نمط التنقل في iOS

CupertinoPageRoute يحاكي UINavigationController من iOS. تدخل الشاشة الجديدة من اليمين، لتغطي الشاشة السابقة. الميزة الرئيسية هي دعم إيماءة التمرير للخلف التفاعلية، المُنفذة عبر CupertinoBackGestureDetector. تتم معالجة هذه الإيماءة حتى أثناء الحركة، مما يوفر سلوكًا طبيعيًا مألوفًا لمستخدمي iPhone.

دورة حياة Route: من الإنشاء إلى التدمير

Route لها دورة حياة خاصة بها، تختلف عن دورة حياة StatefulWidget العادي. فهم هذه الدورة ضروري للتهيئة الصحيحة للبيانات والاشتراكات في التدفقات وتحرير الموارد عند إغلاق الشاشة.

مراحل دورة حياة Route

تتكون دورة حياة 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 توفر آليات لنقل البيانات سواء عند الدخول (عند الإنشاء) أو عند الخروج (عند الانتهاء). نقل البيانات بشكل صحيح عبر Route يلغي الحاجة للمتغيرات العامة و InheritedWidget، مما يجعل التنقل آمنًا من حيث النوع وقابلًا للتنبؤ.

لنقل البيانات إلى شاشة جديدة، استخدم مُنشئ الـ widget المستقبل أو الوسيط arguments في Navigator.pushNamed. داخل Route، البيانات متاحة عبر RouteSettings.arguments، المخزنة في كائن Route. هذا النهج يعمل مع جميع أنواع Route — MaterialPageRoute و CupertinoPageRoute والتطبيقات المخصصة.

لإرجاع البيانات، استخدم الوسيط الثاني لـ Navigator.pop(context, result). Navigator.push يعيد Future، والذي يكتمل بالقيمة المُمرَرة إلى pop. إذا تم استدعاء pop بدون وسيط، يكتمل Future بقيمة null. هذه الآلية مشابهة لـ startActivityForResult في Android ومعالج الإكمال في iOS، لكنها مطبقة عبر Dart Futures.

نقل البيانات عبر مُنشئ Route

عند استدعاء Navigator.push مباشرة مع MaterialPageRoute، يتم تمرير البيانات عبر مُنشئ الشاشة الهدف. لا يتم استخدام MethodChannel — هذا تفاعل Dart خالص. هذا النهج مفضل للنقل الآمن للأنواع للكائنات المعقدة.

مثال إنشاء Route مخصص

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

dart
// 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 و Widget في Flutter؟

Route هو كائن يدير شاشة على مستوى التنقل: يخزن الرسوم المتحركة و ModalBarrier ودورة الحياة. Widget هو وصف لجزء من الواجهة. Route تحتوي على Widget بداخلها، ولكنها توفر أيضًا خدمات (طبقة التراكب، رسوم Hero المتحركة) غير متاحة للـ widgets العادية. Route واحدة يمكن أن تحتوي على تسلسل هرمي معقد من widgets بأي عمق.

كيفية إنشاء Route برسوم متحركة مخصصة؟

استخدم PageRouteBuilder مع معاملات pageBuilder (بناء الشاشة) و transitionsBuilder (تعريف الرسوم المتحركة). في transitionsBuilder، تتوفر animation (0.0–1.0) و secondaryAnimation للرسوم المتحركة المتوازية. للتحكم الكامل، أنشئ فئة فرعية من Route وoverride buildPage و createAnimationController و buildTransitions، مما يتيح الوصول إلى AnimationController منخفض المستوى.

كيفية نقل كائن معقد بين Route؟

لنقل كائنات معقدة، استخدم مُنشئ الشاشة الهدف عند استدعاء Navigator.push مباشرة أو معامل arguments مع pushNamed. تأكد من أن الكائن قابل للتسلسل (Map أو JSON أو فئة مخصصة). للنقل الآمن من حيث النوع في Flutter، استخدم نماذج freezed أو json_serializable التي تضمن إلغاء تسلسل صحيح عند التمرير عبر RouteSettings.

لماذا قد لا تستدعي Route dispose؟

Route.dispose لا يتم استدعاؤها إذا بقيت Route في مكدس Navigator. على سبيل المثال، عند فتح Route جديدة، تنتقل Route القديمة إلى حالة غير نشطة ولكنها لا تُدمر — تبقى في المكدس للعودة السريعة. يتم استدعاء dispose فقط عند إزالة Route من المكدس عبر pop أو pushReplacement أو pushAndRemoveUntil. لتحرير الموارد، استخدم dispose الخاص بـ State داخل Route، وليس dispose الخاص بـ Route نفسها.

كيفية التحقق من Route النشطة حاليًا؟

استخدم ModalRoute.of(context) للحصول على Route الحالية من BuildContext. الخاصية ModalRoute.isActive تظهر ما إذا كانت Route هي الشاشة المرئية حاليًا. ModalRoute.isCurrent — true إذا كانت Route هي قمة المكدس. لمراقبة تغييرات المكدس، اشترك في مراقبي Navigator عبر RouteAware و RouteObserver، اللذان يبلغان عن تغييرات Route النشطة.

الملخص

  • Route — فئة شاشة مجردة في Flutter مع دورة حياة (didPush, didPop, didReplace, didChangeNext) ودعم لـ ModalBarrier ورسوم Hero المتحركة
  • MaterialPageRoute — تطبيق لنظام Android مع رسوم انزلاق من الأسفل وظل و SafeArea تلقائي
  • CupertinoPageRoute — تطبيق لنظام iOS مع رسوم انزلاق من اليمين وإيماءة تمرير للخلف تفاعلية
  • PageRouteBuilder — أداة لإنشاء Route برسوم متحركة مخصصة عبر transitionsBuilder و AnimationController
  • نقل البيانات — عبر مُنشئ Route (push) أو arguments (pushNamed) عند الدخول؛ عبر Navigator.pop(context, result) عند الخروج مع Future
  • دورة الحياة — أربع مراحل: انتقال (didPush)، نشط، غير نشط (مغطى بـ Route أخرى)، مهمل (didPop + dispose)
  • عزل الشاشات — كل Route لها BuildContext وحالة خاصين بها، مما يمنع التسرب ويبسط إدارة البيانات

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا