أفضل الممارسات لتحسين أداء تطبيق فلاتر

  • تجربة المستخدم السيئة
  • إستخدام const
  • إستخدام البرمجة غير المتزامنة
  • عدم استخدم setState() على الواجهة كاملة
  • إستخدم StringBuffer
  • لا تقم باستدعاء الدوال داخل دالة الـ build()
  • إستعمل Lazy Builders مع Grid و List
  • عدم عمل إنهاء أو تحرير للخدمات التي لا يتم استخدامها
  • قم بتحسين الصور

تجربة المستخدم السيئة

الكثير من المطورين يهتمون بجعل واجهة تطبيقاتهم جميلة و متجاهلين أهميّة سرعة عمله فتكون النتيجة:

  • تطبيق بطيء.
  • يستهلك الموارد و يستنفذ البطارية.
  • تجربة سيئة تؤدي الى فقدان المستخدمين.

في هذا المقال سنتعرف على بعض من أفضل الممارسات التي يمكنك تطبيقها من أجل تحسين أداء تطبيقات فلاتر.


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

إستخدام const

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

مثال

const Text('Hello world, use const always')

إستخدام البرمجة غير المتزامنة

عند استدعاء دوال في ثريد واجهة المستخدم ( UI Thread ) من الأفضل أن تقوم باستخدام async await لكي يتم تنفيذها بشكل غير متزامن و عدم التسبب بتعليق في واجهة المستخدم إذا كانت العمليات تأخذ وقت طويل جداً يمكنك استخدام compute() أو isolate() فهي مصممة للعمليات التي تأخذ وقت طويل في التنفيذ

مثال

// ❌ تجنب ما يلي 
onTap: () { someHeavyTask(); } 

// ✅ استخدم ما يلي 
onTap: (){ compute<void,void>(someHeavyTask, null); }

كمثال، قم بعمل CircularProgressIndicator و بأسفله زر و قم بتجريب الطريقتين على هذه الدالة.

مثال

Future<void> someHeavyTask(dynamic arg) async {

    Stopwatch stopwatch = Stopwatch()..start();
    String fullText = "";
    
    for (int i = 0; i < 100000; i++) {
        fullText += " $i";
    }
    
    print('with string concatenation ${stopwatch.elapsedMilliseconds / 1000}');
}

عدم استخدم setState() على الواجهة كاملة

حاول تقليل عمليات الـ Rebuild عن طريق تقسيم الواجهة إلى إجزاء أصغر و الـ Stateful تكون في أصغر جزء ممكن من الـ widget لتكون مستقلة و لا تعمل إعادة بناء للواجهة بالكامل عند عمل setState().

إستخدم StringBuffer

إستعمال += عند دمج النصوص الطويلة يجعل العملية مكلفة و تستغرق وقت أطول و لذلك ينصح بإستعمال الـStringBuffer كحل فعّال لتجميع النصوص الطويلة ثم عرضها مرة واحدة.

مثال

// ❌ تجنب استعمال الأسلوب التالي لأنه بطيء جداً و يستهلك الذاكرة
var text = '';

for (var i = 0; i < 100000; i++) {
    text += 'عدد: $i\n';
}
    
print(text); // جملة الطباعة هذه تتنفذ بعد حوالي 5 ثواني تقريباً

// ✅ إستخدم الأسلوب التالي فهو سريع و فعّال
final buffer = StringBuffer();

for (var word in words) {
    buffer.write(word);
}

print(buffer.toString()); // جملة الطباعة هذه تتنفذ بعد حوالي 0.16 ثانية تقريباً

لا تقم باستدعاء الدوال داخل دالة الـ build()

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

مثال: بدلاً من جعل الواجهة كاملة تقوم بإعادة البناء عند الضغط على زر الإعجاب قم بعمل StatefulWidget منفصلة لزر الاعجاب.

إستعمل Lazy Builders مع Grid و List

لا تقم ببناء جميع عناصر القوائم الطويلة كالرسائل دفعة واحدة لأن ذلك سيؤدي لبطئ في التطبيق بل قم باستخدام Lazy Builders مثل ListView.builder و GridView.builder و هكذا بدلاً من يتم عرضها جميعها مرة واحدة يتم عرض العناصر التي تظهر في الواجهة فقط و يتم التخلص منها عندما تبعدها عن الشاشة و بذلك تقوم بالمحافظة على أداء التطبيق.

مثال

// ❌ تجنب أن تقوم ببناء جميع العناصر مرة واحدة كما يلي
ListView(
    children: messages.map((item) => Message(item.text)
); 

// ✅ قم ببناء العناصر الظاهرة على الشاشة فقط كما يلي
ListView.builder(
    itemCount: messages.length,
    itemBuilder: (context, index) => Message(item[index].text),
);

عدم عمل إنهاء أو تحرير للخدمات التي لا يتم استخدامها

عند استخدام كائنات مثل TextEditingController أو AnimationController أو StreamSubscription فإنها تحجز موارد في الذاكرة. إذا خرجت من الشاشة دون تحرير ( Dispose ) هذه الموارد، فإنها تبقى في الذاكرة و تسبب مشكلة تسمى تسريب الذاكرة ( Memory Leak ). مع تكرار هذه العملية، يستهلك تطبيقك ذاكرة أكبر و أكبر حتى يصبح بطيئاً أو يتعطل.

الحل: دائماً قم بتحرير هذه الموارد في دالة dispose() الخاصة بالـ State.

مثال

@override
void dispose() {
  controller.dispose();
  super.dispose();
}

قم بتحسين الصور

الصور غير المحسنة هي من أكبر أسباب بطئ التطبيق و هنا بعض النقاط التي يجب أن تنتبه إليها عند التعامل مع الصور:

  • ضغط الصور قبل رفعها في التطبيق.
  • إستخدام الحجم المناسب للصورة في المكان المناسب. فمثلاً لا يجب أن تقوم بعرض صورة بحجم 1000x1000 في مساحة 200x200.
  • إستخدام صيغ صور صغيرة الحجم مثل صيغة WebP لعرض الصور فهي توفر جودة ممتازة وحجم اصغر مقارنة بصيغة png أو jpg.
  • متى ما كان بالإمكان تخزين الصور في الـ الـ Cache إفعل ذلك و يمكنك استخدام مكتبة cached_network_image.

تذكر دائماً أن تضع أهمية لتحسين أداء التطبيق بنفس أهمية إضافة مميزات جديدة للتطبيق من أجل تحسين تجربة المستخدم و الحفاظ عليه.


إذا واجهتك مشكلة في أداء تطبيقك و قمت بحلها، شارك الحل معنا.

آخر تحديث في 07-01-2026

Rashed Kamal

مهندس برمجيات و متخصص في مجال تطوير تطبيقات الجوال و اعمل ب Kotlin و Flutter و اقوم بكتابة المحتوى و المقالات التقنية.

Rashedswen.dev

تعليقات

لا يوجد أي تعليق بعد

أضف تعليق

يجب تسجيل الدخول حتى تتمكن من إضافة تعليق أو رد.