إعادة التحميل السريع وإعادة التشغيل السريع
ما هو إعادة التحميل السريع؟
إعادة التحميل السريع هي واحدة من أقوى ميزات Flutter. تسمح لك بحقن الشيفرة المصدرية المحدثة في آلة Dart الافتراضية (VM) العاملة دون إعادة تشغيل التطبيق بالكامل. النتيجة؟ ترى تغييراتك منعكسة على الشاشة في أقل من ثانية مع الحفاظ على الحالة الحالية لتطبيقك.
هذا يعني إذا كنت في شاشة معينة أو ملأت نموذجاً أو مررت إلى موضع معين كل تلك الحالة محفوظة عند إعادة التحميل السريع. يتم تطبيق تغييرات الشيفرة فقط.
كيف تعمل إعادة التحميل السريع داخلياً
فهم الآلية الداخلية يساعدك على معرفة متى ولماذا تعمل أو تفشل:
- تجري تغييراً في الشيفرة وتحفظ الملف (أو تضغط زر إعادة التحميل)
- تحدد آلة Dart الافتراضية ملفات المصدر التي تغيرت منذ آخر ترجمة
- يتم ترجمة شيفرة Dart المعدلة إلى ملفات kernel (ترجمة تزايدية)
- يتم حقن ملفات kernel الجديدة في آلة Dart الافتراضية العاملة
- تقوم VM بتحديث الفئات المتأثرة بتعريفات الحقول والدوال الجديدة
- يطلق إطار Flutter إعادة بناء شجرة الودجات بدءاً من الجذر
- يستدعي الإطار دوال
build()على الودجات المتأثرة - تظهر واجهة المستخدم المحدثة على الشاشة
إعادة التحميل السريع عملياً
// قبل: خلفية زرقاء
Scaffold(
backgroundColor: Colors.blue,
body: Center(
child: Text('Hello World'),
),
)
// بعد الحفظ: التغيير إلى أخضر -- يُطبق فوراً
Scaffold(
backgroundColor: Colors.green,
body: Center(
child: Text('Hello World'),
),
)
إعادة التحميل السريع مقابل إعادة التشغيل السريع مقابل إعادة التشغيل الكامل
يوفر Flutter ثلاثة مستويات من إعادة التحميل كل منها بمقايضات مختلفة بين السرعة والاكتمال:
إعادة التحميل السريع (الأسرع)
تحقن تغييرات الشيفرة دون فقد حالة التطبيق. تستغرق أقل من ثانية واحدة. مثالية لتعديلات واجهة المستخدم وتغييرات الأنماط والتحديثات المنطقية البسيطة.
تشغيل إعادة التحميل السريع
# من الطرفية (عندما يعمل التطبيق بـ flutter run)
# اضغط: r
# VS Code
# اضغط: Ctrl+S (الحفظ التلقائي يشغل إعادة التحميل)
# أو: انقر زر إعادة التحميل (أيقونة البرق)
# Android Studio / IntelliJ
# اضغط: Ctrl+S (أو Cmd+S على macOS)
# أو: انقر زر إعادة التحميل في شريط الأدوات
إعادة التشغيل السريع (سرعة متوسطة)
تعيد تشغيل التطبيق من الصفر بدون إعادة ترجمة كاملة. تستغرق 2-5 ثوانٍ. تُفقد حالة التطبيق لكنها أسرع بكثير من إعادة التشغيل الكامل. استخدمها عندما لا تلتقط إعادة التحميل السريع تغييراتك.
تشغيل إعادة التشغيل السريع
# من الطرفية
# اضغط: R (حرف R كبير)
# VS Code
# اضغط: Ctrl+Shift+F5
# أو: انقر زر إعادة التشغيل (أيقونة السهم الدائري)
# Android Studio / IntelliJ
# انقر زر إعادة التشغيل في شريط الأدوات
إعادة التشغيل الكامل (الأبطأ)
توقف التطبيق تماماً وتعيد بناءه من الصفر. تستغرق 10-30+ ثانية. مطلوبة عند تغيير الشيفرة الأصلية أو إضافة إضافات أو تعديل ملفات خاصة بالمنصة.
تشغيل إعادة التشغيل الكامل
# أوقف التطبيق وشغله مرة أخرى
# الطرفية: اضغط q للخروج ثم شغل flutter run مرة أخرى
# VS Code: أوقف التصحيح ثم ابدأ مرة أخرى (F5)
# Android Studio: أوقف وأعد تشغيل التطبيق
r). إذا لم تظهر التغييرات جرب إعادة التشغيل السريع (اضغط R). قم بإعادة التشغيل الكامل فقط إذا لم ينجح أي منهما وهو ما يعني عادة أنك غيرت شيئاً خارج شيفرة Dart (مثل إضافة تبعية جديدة أو تعديل ملفات تكوين Android/iOS).متى تعمل إعادة التحميل السريع
تعمل إعادة التحميل السريع بشكل موثوق في هذه السيناريوهات الشائعة:
1. تغيير خصائص الودجات
تعديل أنماط الودجات
// تغيير الألوان والأحجام والحشو والهوامش
Container(
padding: const EdgeInsets.all(16), // التغيير من 8 إلى 16
color: Colors.red, // التغيير من أزرق إلى أحمر
child: Text(
'نص منسق',
style: TextStyle(
fontSize: 24, // التغيير من 18 إلى 24
fontWeight: FontWeight.bold, // إضافة عريض
),
),
)
2. تعديل دوال Build
تحديث شجرة الودجات
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('مرحباً'),
// إضافة ودجات جديدة -- إعادة التحميل تلتقط هذا
Text('هذا سطر جديد!'),
ElevatedButton(
onPressed: () {},
child: Text('زر جديد'),
),
],
);
}
3. تغيير أجسام الدوال
تحديث المنطق
void _incrementCounter() {
setState(() {
// التغيير من _counter++ إلى _counter += 5
_counter += 5;
});
}
متى لا تعمل إعادة التحميل السريع
لإعادة التحميل السريع قيود. في هذه الحالات تحتاج إعادة تشغيل سريع أو كامل:
1. تغييرات المتغيرات العامة والحقول الثابتة
التغييرات العامة/الثابتة تتطلب إعادة تشغيل سريع
// تغيير هذه يتطلب إعادة تشغيل سريع (R) وليس إعادة تحميل سريع (r)
int globalCounter = 0; // تغيير القيمة الابتدائية
const String appName = 'MyApp'; // تغيير قيم const
class MyService {
static final instance = MyService._(); // تغيير الحقول الثابتة
MyService._();
}
2. تغييرات initState()
تغييرات initState تحتاج إعادة تشغيل سريع
@override
void initState() {
super.initState();
// التغييرات هنا لن تسري بإعادة التحميل السريع
// لأن initState() تعمل مرة واحدة فقط عندما تُدرج
// الودجت لأول مرة في الشجرة
_counter = 100; // هذا التغيير يحتاج إعادة تشغيل سريع
}
3. تغييرات أنواع Enum
تغييرات Enum تتطلب إعادة تشغيل سريع
// إضافة أو إزالة قيم enum يتطلب إعادة تشغيل سريع
enum Status {
active,
inactive,
pending, // إضافة هذا يتطلب إعادة تشغيل سريع
}
4. تغييرات معاملات الأنواع العامة
تغييرات الأنواع العامة
// تغيير معاملات النوع يتطلب إعادة تشغيل سريع
class MyList<T> {
// التغيير من MyList<T> إلى MyList<T extends Comparable>
// يتطلب إعادة تشغيل سريع
}
إعادة التحميل مع الحفاظ على الحالة
أحد أكثر جوانب إعادة التحميل السريع قيمة أنها تحافظ على State لـ StatefulWidget. هذا مفيد جداً أثناء التطوير.
مثال على الحفاظ على الحالة
class _CounterPageState extends State<CounterPage> {
int _count = 0;
String _message = 'مرحباً';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// إذا كان _count يساوي 42 وغيرت نمط النص أدناه
// ستحدث إعادة التحميل النمط لكن _count يبقى 42
Text(
'العدد: \$_count',
style: TextStyle(
fontSize: 32, // غير هذا...
color: Colors.purple, // ...أو هذا
),
),
Text(_message),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++),
child: Icon(Icons.add),
),
);
}
}
في هذا المثال إذا نقرت الزر 42 مرة ثم غيرت fontSize من 32 إلى 48 ستحدث إعادة التحميل حجم النص لكن _count سيبقى 42. لا تحتاج للنقر 42 مرة أخرى للعودة لنفس الحالة.
أمثلة عملية -- تعديل واجهة المستخدم مباشرة
دعنا نستعرض سير عمل عملي لاستخدام إعادة التحميل لتصميم ودجت بطاقة تكرارياً.
الخطوة 1: البداية ببطاقة أساسية
Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text('بطاقتي'),
),
)
الخطوة 2: إعادة تحميل -- إضافة ارتفاع وشكل
Card(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: EdgeInsets.all(16),
child: Text('بطاقتي'),
),
)
الخطوة 3: إعادة تحميل -- إضافة لون ومحتوى إضافي
Card(
elevation: 8,
color: Colors.teal.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'عنوان البطاقة',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 8),
Text('هذا هو وصف البطاقة.'),
],
),
),
)
كل تغيير يستغرق أقل من ثانية للظهور على الشاشة. حلقة الملاحظات السريعة هذه تسمح لك بالتجربة مع تصميمات مختلفة بسرعة دون انتظار إعادة بناء كاملة.
ملخص اختصارات لوحة المفاتيح لإعادة التحميل
إليك مرجعاً سريعاً لجميع اختصارات لوحة المفاتيح لإعادة التحميل:
مرجع اختصارات لوحة المفاتيح
# الطرفية (flutter run)
r -- إعادة التحميل السريع
R -- إعادة التشغيل السريع
q -- خروج
d -- فصل (ترك التطبيق يعمل)
h -- عرض قائمة المساعدة
v -- فتح Flutter DevTools
w -- طباعة شجرة الودجات
t -- طباعة شجرة العرض
p -- تبديل طلاء التصحيح
# VS Code
Ctrl+S / Cmd+S -- حفظ (يشغل إعادة التحميل)
Ctrl+Shift+F5 -- إعادة التشغيل السريع
F5 -- بدء/متابعة التصحيح
Shift+F5 -- إيقاف التصحيح
# Android Studio / IntelliJ
Ctrl+S / Cmd+S -- حفظ (يشغل إعادة التحميل)
Ctrl+F5 -- إعادة التشغيل السريع
Shift+F10 -- تشغيل
Ctrl+F2 -- إيقاف
القيود والمحاذير
كن على دراية بهذه القيود الإضافية:
- تغييرات الشيفرة الأصلية: تعديل
AndroidManifest.xmlأوInfo.plistأو ملفات Gradle أو Podfile يتطلب إعادة تشغيل كامل - إضافة حزم جديدة: بعد تشغيل
flutter pub addأو تعديلpubspec.yamlتحتاج إعادة تشغيل كامل - تغييرات الأصول: إضافة صور أو خطوط جديدة لمجلد الأصول يتطلب إعادة تشغيل كامل
- تغييرات دالة main: تغييرات دالة
main()أوrunApp()تحتاج إعادة تشغيل سريع - أخطاء الترجمة: إذا كانت شيفرتك تحتوي أخطاء ستفشل إعادة التحميل. أصلح الأخطاء وحاول مرة أخرى
- منصة الويب: إعادة التحميل على الويب تستخدم آلية مختلفة (إعادة تشغيل سريع) لا تحافظ على الحالة
أفضل الممارسات للتطوير الفعال
اتبع هذه الممارسات للاستفادة القصوى من إعادة التحميل السريع:
- اجعل الودجات صغيرة: ودجات أصغر تعني نطاقات إعادة بناء أصغر مما يجعل إعادة التحميل أسرع
- استخدم مُنشئات const: الودجات المعلمة كـ
constلا تُعاد بناؤها أثناء إعادة التحميل مما يحسن الأداء - احفظ بشكل متكرر: اضبط محررك للحفظ التلقائي مما يشغل إعادة التحميل تلقائياً
- راقب وحدة التحكم: تعرض الطرفية حالة إعادة التحميل وأي تحذيرات أو أخطاء
- اعرف متى تعيد التشغيل: إذا بدا شيء خاطئاً بعد إعادة التحميل قم بإعادة التشغيل السريع قبل قضاء وقت في التصحيح
ملخص
في هذا الدرس تعلمت:
- إعادة التحميل السريع تحقن شيفرة محدثة في آلة Dart الافتراضية العاملة في أقل من ثانية
- الفرق بين إعادة التحميل السريع (تحافظ على الحالة) وإعادة التشغيل السريع (تفقد الحالة لكن سريعة) وإعادة التشغيل الكامل (إعادة بناء كاملة)
- تعمل إعادة التحميل لتغييرات الودجات ودوال build وتحديثات أجسام الدوال
- لا تعمل إعادة التحميل للمتغيرات العامة وتغييرات initState والتعدادات وتغييرات الأنواع العامة
- يتم الحفاظ على الحالة أثناء إعادة التحميل وهو لا يُقدر بثمن لتطوير واجهة المستخدم التكراري
- اختصارات لوحة المفاتيح الأساسية:
rلإعادة التحميل وRلإعادة التشغيل - متى تستخدم كل نوع من إعادة التحميل لأقصى إنتاجية
تمرين عملي
أنشئ تطبيق Flutter بسيطاً بـ StatefulWidget يحتوي عداداً وحقل نص. شغل التطبيق وزد العداد إلى 10. ثم بدون إيقاف التطبيق استخدم إعادة التحميل لـ: (1) تغيير نمط النص، (2) تغيير لون الخلفية، (3) إضافة زر جديد. تحقق أن العداد يبقى عند 10 بعد كل إعادة تحميل. ثم جرب تغيير القيمة الابتدائية في initState() ولاحظ أن إعادة التحميل لا تطبق التغيير -- تحتاج إعادة تشغيل سريع.