Widget Tree: ما هو، هيكله ودوره في شجرة العناصر

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

Widget Tree هي بنية هرمية للعناصر في Flutter تحدد تخطيط واجهة المستخدم. كل عنصر في الواجهة، من زر إلى شاشة كاملة، يمثله عنصر منفصل متداخل داخل حاوية رئيسية. يقوم Flutter بتحديث Widget Tree عند كل تغيير في الحالة — يقارن الإطار الشجرة الجديدة بالقديمة ويطبق الحد الأدنى من التغييرات. وفقًا Flutter Team, 2025، يؤثر هيكل الشجرة الفعال بشكل مباشر على سلاسة الرسوم المتحركة واستجابة الواجهة.

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

  • Widget Tree هي تسلسل هرمي حيث كل عنصر Flutter هو عقدة، ويعكس التداخل تخطيط واجهة المستخدم.
  • كل إعادة بناء (rebuild) تعيد إنشاء تكوين العناصر، لكنها لا تعيد رسم الشاشة بالضرورة — Element و RenderObject يتوليان ذلك.
  • StatelessWidget ليس له حالة داخلية، بينما يخزن StatefulWidget البيانات التي تؤثر على إعادة بناء الشجرة.
  • المفاتيح (Key) تساعد Flutter في التعرف على العناصر أثناء إعادة البناء، مما يمنع فقدان الحالة.
  • عمق الشجرة يؤثر على الأداء — التداخل المفرط يمكن أن يبطئ مرحلة التخطيط في العرض.

ما هو Widget Tree في Flutter؟

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

النهج التعريفي لـ Flutter

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

dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Widget Tree")),
        body: Center(
          child: Column(
            children: [
              Text("مرحبًا، Flutter"),
              ElevatedButton(
                onPressed: () {},
                child: Text("اضغطني"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

في هذا المثال، تتكون Widget Tree من MaterialApp و Scaffold و AppBar و Center و Column و Text و ElevatedButton. كل عنصر من هذه العناصر هو عقدة في الشجرة. عندما تتغير حالة التطبيق، يستدعي Flutter طريقة build مرة أخرى ويقارن النتيجة بالشجرة السابقة.

هيكل Widget Tree: العناصر الجذرية والتابعة

تبدأ Widget Tree بعنصر جذري يتم تمريره إلى طريقة runApp. العنصر الجذري عادة ما يكون MaterialApp أو CupertinoApp أو WidgetsApp — وهو يحدد الإعدادات العامة للتطبيق. من الجذر، تتفرع الشجرة إلى عناصر تابعة، يمكن لكل منها أن يحتوي على عناصر خاصة به.

العناصر ذات الطفل الواحد والمتعددة الأطفال

تنقسم العناصر في Flutter إلى single-child (تقبل طفلًا واحدًا عبر معامل child) و multi-child (تقبل قائمة من الأطفال عبر children). أمثلة على single-child: Center و Padding و SizedBox و Container. Multi-child: Column و Row و Stack و ListView و GridView. هذا الاختلاف يؤثر على هيكل Widget Tree: العناصر multi-child تنشئ أشجارًا أوسع، بينما single-child تنشئ أشجارًا أعمق.

دور BuildContext في الشجرة

BuildContext هو موقع العنصر في Widget Tree. كل عنصر له BuildContext الخاص به، الذي يتم تمريره إلى طريقة build ويستخدم للوصول إلى العناصر الأم والسمة و MediaQuery وغيرها من InheritedWidgets. يعمل BuildContext كجسر بين العنصر وعنصره في Element Tree.

dart
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final mediaQuery = MediaQuery.of(context);
    return Container(
      color: theme.colorScheme.primary,
      child: Text(
        "عرض الشاشة: ${mediaQuery.size.width}"
      ),
    );
  }
}

في هذا المثال، يتم استخدام BuildContext للحصول على السمة وأبعاد الشاشة. يصعد Flutter في Widget Tree إلى أقرب Theme و MediaQuery، وهما من InheritedWidgets. يوضح هذا كيف يربط السياق العنصر بموقعه في التسلسل الهرمي.

كيف يبني Flutter Widget Tree عند بدء التشغيل

عند بدء تشغيل تطبيق Flutter، يتم استدعاء الدالة runApp، التي تأخذ العنصر الجذري وتبدأ في بناء Widget Tree. تتضمن العملية ثلاث مراحل: إنشاء تكوين العناصر، تشكيل Element Tree، وبناء RenderObject Tree للعرض الفعلي.

المرحلة 1: إنشاء العنصر الجذري

تنشئ الدالة runApp عنصرًا جذريًا عبر WidgetsFlutterBinding، الذي يربط الإطار بمحرك الرسومات. يتم وضع العنصر الجذري في الشجرة، ويستدعي Flutter طريقة build لملئها بالعناصر التابعة. كل استدعاء لـ build يولد رسمًا بيانيًا فرعيًا جديدًا لـ Widget Tree.

المرحلة 2: التخطيط الأولي

بعد بناء Widget Tree، يقوم Flutter بتنفيذ تخطيط أولي — حساب أحجام ومواقع جميع العناصر. تبدأ هذه العملية من الجذر وتنتشر لأسفل الشجرة. يتلقى كل عنصر قيودًا من العنصر الأم ويعيد حجمًا محسوبًا. إذا لم تتطابق الأحجام، يولد Flutter خطأ في التخطيط.

المرحلة 3: العرض على الشاشة

بعد اكتمال التخطيط، يشرع Flutter في عرض كل عنصر. يحول RenderObject وصف الواجهة إلى أوامر رسومية تنفذها وحدة معالجة الرسومات عبر Skia أو Impeller. تتكرر العملية بأكملها — من Widget Tree إلى البكسلات — عند كل تغيير في الحالة بمعدل يصل إلى 120 إطارًا في الثانية.

StatelessWidget و StatefulWidget في التسلسل الهرمي للشجرة

StatelessWidget هو عنصر ليس له حالة داخلية قابلة للتغيير. مظهره محدد بالكامل بواسطة معاملات الإدخال الممررة عبر المنشئ. إذا لم تتغير المعاملات، لا يتم إعادة بناء StatelessWidget. هذا يجعله خفيفًا من حيث الأداء.

متى تستخدم StatelessWidget

استخدم StatelessWidget لـ عناصر الواجهة الثابتة: الأيقونات، تسميات النص، الفواصل الزخرفية، والأزرار البسيطة بدون منطق داخلي. وفقًا لوثائق Flutter، حوالي 70% من العناصر في تطبيق نموذجي يمكن أن تكون StatelessWidget، مما يقلل من حمل جامع القمامة ويسرع إعادة البناء.

StatefulWidget وإدارة الحالة

StatefulWidget ينشئ كائن State يستمر بين عمليات إعادة بناء العنصر. عندما تتغير الحالة (عبر setState)، يضع Flutter علامة على العنصر كـ “متسخ” ويعيد بنائه في الإطار التالي. يسمح StatefulWidget بتنفيذ العناصر التفاعلية: حقول الإدخال والرسوم المتحركة والمؤقتات والقوائم الديناميكية.

dart
class CounterWidget extends StatefulWidget {
  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text("العدد: $_count"),
        ElevatedButton(
          onPressed: () {
            setState(() => _count++);
          },
          child: Text("زيادة"),
        ),
      ],
    );
  }
}

في هذا المثال، يستخدم StatefulWidget setState لتحديث العداد. عندما يتم تحديث الحالة، يعيد Flutter بناء الجزء المتغير فقط من Widget Tree — CounterWidget وأحفاده. لا يتم إعادة بناء العناصر الأم، وهي ميزة رئيسية للنموذج التعريفي لـ Flutter.

كيف يرتبط Widget Tree مع Element Tree

Widget Tree هي طبقة التكوين، بينما Element Tree هي الرابط الوسيط بين العناصر والعرض الفعلي. كل عنصر في Widget Tree ينشئ عنصرًا في Element Tree، يخزن مرجعًا للعنصر ويدير دورة حياته. هذه البنية تسمح لـ Flutter بمعالجة التغييرات بكفاءة.

إنشاء عنصر من Widget

عندما يواجه Flutter عنصرًا لأول مرة، يستدعي طريقة createElement، التي تنشئ عنصرًا مطابقًا. بالنسبة لـ StatelessWidget، يتم إنشاء StatelessElement؛ بالنسبة لـ StatefulWidget، يتم إنشاء StatefulElement، الذي يقوم أيضًا بإنشاء كائن State. يستمر العنصر بين دورات إعادة البناء، حتى إذا تم إعادة إنشاء العنصر.

آلية المفاتيح (Keys) في Element Tree

Key هو معرف يساعد Flutter في مطابقة العناصر من Widget Tree القديم والجديد. إذا كان للعنصر Key، يستخدمه Flutter للعثور على العنصر المقابل بدلاً من موقعه في الشجرة. المفاتيح ضرورية عند العمل مع القوائم الديناميكية حيث قد يتغير ترتيب العناصر.

dart
ListView(
  children: items.map((item) => ListItem(
    key: ValueKey(item.id),
    data: item,
  )).toList(),
)

بدون Key، يطابق Flutter العناصر حسب الموقع، مما قد يؤدي إلى حفظ حالة غير صحيح عند تغيير الترتيب. يضمن ValueKey بمعرف فريد أن يحتفظ كل عنصر بحالته بغض النظر عن موقعه في القائمة.

تأثير Widget Tree على الأداء

هيكل Widget Tree يؤثر مباشرة على أداء تطبيق Flutter. الأشجار العميقة مع العديد من العناصر المتداخلة تتطلب وقتًا أطول لمرحلة التخطيط وتزيد من استخدام الذاكرة. توفر Flutter DevTools أدوات لتحليل Widget Tree وتحديد الاختناقات.

التداخل المفرط

كل مستوى تداخل يضيف حسابات إضافية أثناء التخطيط والرسم. بدلاً من التداخل العميق المتسلسل، استخدم هياكل أكثر تسطحًا. على سبيل المثال، Row مع Expanded يمكن أن يحل محل عدة Containers متداخلة مع Align. وفقًا لـ Flutter Team، يمكن أن يقلل تحسين الشجرة من وقت التخطيط بنسبة تصل إلى 40%.

  • التخطيط — كل عنصر أب يمرر القيود إلى العناصر التابعة ويستقبل الأحجام مرة أخرى، مما يؤدي مع التداخل العميق إلى إنشاء سلسلة من الحسابات.
  • الرسم — كل عنصر يمكن أن ينشئ طبقة منفصلة للعرض، والتداخل المفرط يزيد من عدد الطبقات.
  • الذاكرة — كل عنصر في Element Tree يستهلك ذاكرة، والعناصر المفرطة تزيد من استهلاك الموارد.

أدوات تحليل Widget Tree

Flutter DevTools توفر أداة “Widget Inspector” التي تظهر Widget Tree الحالية في الوقت الفعلي. يمكن للمطور تحديد أي عنصر على الشاشة ورؤية مكانه في الشجرة ومعاملاته وقيود التخطيط. هذا يساعد في تحديد التداخل غير المتوقع وعمليات إعادة البناء المفرطة ومشاكل الأبعاد.

RepaintBoundary لتحسين الأداء

RepaintBoundary هو عنصر يعزل جزءًا من Widget Tree للعرض المستقل. إذا تغير المحتوى داخل RepaintBoundary، يتم إعادة رسم منطقته فقط، وليس الشاشة بأكملها. استخدم RepaintBoundary للرسوم المتحركة والقوائم والعناصر الأخرى التي يتم تحديثها بشكل متكرر.

dart
RepaintBoundary(
  child: CustomPaint(
    painter: MyPainter(),
    child: SizedBox(
      width: 200,
      height: 200,
    ),
  ),
)

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

الأسئلة الشائعة

ما الفرق بين Widget Tree و Element Tree؟

Widget Tree هي وصف تعريفي للواجهة يتم إعادة إنشائه عند كل إعادة بناء. Element Tree يستمر بين التحديثات ويدير دورة الحياة والحالة ومطابقة العناصر مع RenderObjects الفعلية.

كم عدد العناصر التي يمكن أن تكون في Widget Tree؟

لا يوجد حد لعدد العناصر، ولكن عمليًا شجرة بها آلاف العناصر يمكن أن تبطئ مرحلة التخطيط. Flutter محسّن للأشجار التي تصل إلى عدة آلاف من العقد؛ للأعداد الأكبر، يُوصى باستخدام virtualisation عبر ListView.builder.

كيف ترى Widget Tree في المصحح؟

استخدم Flutter DevTools — علامة التبويب “Widget Inspector”. قم بتشغيل التطبيق في وضع التصحيح، وافتح DevTools في المتصفح، واختر أي عنصر على الشاشة لعرض مكانه في Widget Tree.

ما هي إعادة بناء Widget Tree؟

إعادة البناء هي عملية إعادة إنشاء تكوين العناصر عندما تتغير الحالة. يستدعي Flutter طريقة build مرة أخرى للعناصر المتغيرة، ويقارن Widget Tree الجديدة مع السابقة ويطبق الحد الأدنى من التغييرات على Element Tree.

كيف تحسن Widget Tree؟

قلل عمق التداخل، استخدم const widgets للعناصر الثابتة، طبق RepaintBoundary لعزل الرسوم المتحركة، وتجنب StatefulWidgets المفرطة حيث يكفي StatelessWidget.

الملخص

  • Widget Tree هي وصف هرمي تعريفي لواجهة المستخدم في Flutter، حيث كل عقدة هي عنصر بتكوين ومعاملات.
  • Flutter يبني Widget Tree عند بدء التشغيل عبر runApp، منفذًا ثلاث مراحل: إنشاء العنصر الجذري والتخطيط والعرض.
  • StatelessWidget ليس له حالة ويعاد بناؤه فقط عندما تتغير معاملات الإدخال؛ StatefulWidget يستخدم setState لإدارة البيانات الديناميكية.
  • Element Tree يستمر بين عمليات إعادة البناء ويربط Widget Tree مع RenderObject Tree عبر العناصر.
  • المفاتيح (Key) تضمن مطابقة صحيحة للعناصر أثناء إعادة البناء، خاصة في القوائم الديناميكية.
  • عمق الشجرة يؤثر على الأداء — التداخل المفرط يزيد من وقت التخطيط واستهلاك الذاكرة.
  • RepaintBoundary يعزل جزءًا من Widget Tree لإعادة رسم محلية، مما يقلل من حمل وحدة معالجة الرسومات أثناء الرسوم المتحركة.

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

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

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

اقرأ أيضًا