Hot Reload — فناوریای که به شما امکان میدهد کد یک اپلیکیشن موبایل در حال اجرا را بدون راهاندازی مجدد و از دست دادن وضعیت فعلی بهروزرسانی کنید. توسعهدهنده کد منبع را تغییر میدهد — پس از یک ثانیه تغییرات روی صفحه دستگاه یا شبیهساز نمایش داده میشود. این ویژگی کلیدی Flutter و React Native است که تکرارهای توسعه را به طور چشمگیری加速 میبخشد: زمان چرخه ویرایش-مشاهده از ۵–۱۰ ثانیه (بازسازی) به ۳۰۰–۵۰۰ میلیثانیه کاهش مییابد. طبق Flutter Documentation, 2025، hot reload کامپایل افزایشی کد تغییر یافته را انجام میدهد و بهروزرسانی را به Dart VM ارسال میکند.
نکات اصلی
Hot Reload — مکانیزم توسعهای است که در آن کد منبع تغییر میکند و بدون توقف اپلیکیشن به برنامه در حال اجرا اعمال میشود. توسعهدهنده فایل را ویرایش میکند، ذخیره میکند و پس از ۰.۳–۲ ثانیه رابط کاربری بهروزرسانی شده روی صفحه نمایش داده میشود. وضعیت اپلیکیشن (شمارندهها، موقعیت اسکرول، دادههای وارد شده) حفظ میشود — توسعهدهنده بافت را از دست نمیدهد.
مفهوم hot reload در ابزارهای اولیه وب (LiveReload, ۲۰۱۰) ظهور کرد و توسط فریمورکهای Flutter (۲۰۱۷) و React Native (۲۰۱۵) برای توسعه موبایل تطبیق داده شد. امروزه hot reload یک ویژگی اجباری فریمورکهای مدرن موبایل است، در کنار پیکربندی debug و پروفایلینگ. بدون hot reload توسعه UI ناکارآمد در نظر گرفته میشود: هر مشاهده تغییر به ۱۰–۳۰ ثانیه برای بازسازی و راهاندازی نیاز دارد.
از نظر فنی hot reload از سه مرحله تشکیل شده است: تشخیص تغییر (file watcher)، کامپایل کد تغییر یافته (incremental compiler) و اعمال (hot patching). هر فریمورک این مراحل را به روش خود پیادهسازی میکند، اما نتیجه یکسان است: حداقل تأخیر بین ویرایش و نمایش.
Hot Reload در Flutter بر اساس معماری Dart VM و کامپایل JIT ساخته شده است. وقتی توسعهدهنده دکمه „Hot Reload” را در IDE فشار میدهد یا فایل را ذخیره میکند، Flutter کامپایل افزایشی کتابخانههای Dart تغییر یافته را به فایلهای kernel (.dill) انجام میدهد. Dart VM این فایلها را بارگذاری میکند و پیادهسازی توابع تغییر یافته را در اپلیکیشن در حال اجرا جایگزین میکند.
// ویجت Flutter با وضعیت حفظ شده در طول hot reload
class CounterWidget extends StatefulWidget {
@override
State createState() => _CounterState();
}
class _CounterState extends State {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('شمارنده: $_counter'),
ElevatedButton(
onPressed: () => setState(() => _counter++),
child: Text('افزایش'),
),
],
);
}
}
در مثال StatefulWidget، CounterWidget فیلد _counter را در طول hot reload حفظ میکند. Dart VM وضعیت (State) را با فراخوانی reassemble() بازآفرینی میکند، اما _counter را صفر نمیکند — مقدار حفظ میشود، مگر اینکه ویجت به طور کامل بازآفرینی شود. Flutter برای همه اشیاء State reassemble() فراخوانی میکند و build() دوباره با کد فعلی و وضعیت حفظ شده اجرا میشود.
چه زمانی hot reload کار نمیکند: اگر متغیر استاتیک (static const)، متغیر سراسری، main()، اعلان کلاس enum/mixin، کد در @override initState() تغییر کرده باشد. در این موارد Hot Restart مورد نیاز است. طبق دادههای Flutter Team (۲۰۲۵)، hot reload در ۸۵–۹۰٪ موارد موفق است؛ ۱۰–۱۵٪ تغییرات نیاز به راهاندازی مجدد کامل دارند.
Dart VM در حالت debug به عنوان کامپایلر JIT کار میکند: کد Dart را از طریق فرمت kernel (معادل بایتکد) تفسیر میکند. Hot reload فایل kernel جدید را بارگذاری میکند و تعاریف قدیمی توابع را جایگزین میکند. VM ایزولهها (isolates) را راهاندازی مجدد نمیکند — همه عملیاتهای ناهمزمان (Future, Stream) به کار خود ادامه میدهند. در حالت release، Dart به صورت AOT (dart2native) کامپایل میشود و hot reload در دسترس نیست.
Fast Refresh (که قبلاً Hot Reloading نامیده میشد) در React Native از Metro bundler استفاده میکند — یک باندلر ماژولار JavaScript که تغییرات فایلها را ردیابی میکند. وقتی توسعهدهنده فایل را ذخیره میکند، Metro فقط ماژول تغییر یافته (HMR — Hot Module Replacement) را کامپایل میکند و بهروزرسانی را از طریق WebSocket به اپلیکیشن در حال اجرا ارسال میکند.
// کامپوننت React Native با حفظ وضعیت در طول hot reload
import React, { useState } from 'react';
import { View, Text, Button } from 'react-native';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<View>
<Text>شمارنده: {count}Text>
<Button title="افزایش"
onPress={() => setCount(c => c + 1)} />
View>
);
};
Fast Refresh وضعیت React (useState, useReducer) را هنگام بهروزرسانی ماژول حفظ میکند. Metro HMR فقط diff ماژول تغییر یافته را ارسال میکند — نه کل باندل. React Native از React Fast Refresh استفاده میکند که توسط تیم React (Dan Abramov, ۲۰۱۹) توسعه یافته است: یک رندر جدید برای کامپوننت تولید میکند، اما وضعیتهای hook و props را اگر امضای کامپوننت تغییر نکرده باشد حفظ میکند.
Fast Refresh در تغییرات زیر کار نمیکند: export کامپوننت، هوکها (useEffect, useMemo)، وابستگیهای ماژولار و ماژولهای بومی (Java/Objective-C). برای چنین تغییراتی Reload (بارگذاری مجدد کامل JS-bundle) یا Rebuild (بازسازی کد بومی) مورد نیاز است. زمان fast refresh — ۲۰۰–۸۰۰ میلیثانیه، reload کامل — ۲–۵ ثانیه.
Hot Reload و Hot Restart — دو حالت بهروزرسانی کد با سناریوهای کاربری متفاوت. Hot Reload برای تغییرات UI (سبکها، چیدمان، رنگها، متنها) مناسب است، زمانی که ساختار کلاسها و نوع وضعیت تغییر نمیکند. Hot Restart هنگام تغییر امضای متدها، افزودن ویجتها/کامپوننتهای جدید در درخت ریشه، تغییر initState و ماژولهای بومی ضروری است.
| ویژگی | Hot Reload | Hot Restart |
|---|---|---|
| سرعت | ۰.۳–۲ ثانیه | ۲–۱۰ ثانیه |
| حفظ وضعیت | بله (متغیرها، state، پشته ناوبری) | خیر (اپلیکیشن از نو راهاندازی میشود) |
| کامپایل | افزایشی (فقط تغییرات) | کامپایل مجدد کامل Dart/JS |
| زمان استفاده | تنظیمات UI، سبکها، متنها، چیدمان | تغییر ساختار، ماژولهای جدید، کد بومی |
| Flutter | Hot Reload (R) | Hot Restart (Shift + R) |
| React Native | Fast Refresh | Reload (Cmd + R) |
استراتژی توصیه شده: با hot reload شروع کنید. اگر تغییرات اعمال نشدند (IDE „Reload needed” نشان میدهد) — hot restart را انجام دهید. در Flutter آیکون دکمه تغییر میکند: صاعقه (⚡) برای hot reload، صاعقه خط خورده — اگر restart مورد نیاز باشد. بازدهی توسعه با hot reload در مقایسه با بازسازیهای کامل ۴۰–۶۰٪ بیشتر است (دادههای JetBrains Developer Survey ۲۰۲۴).
تزریق کد (code injection) — مکانیزم مشترک hot reload که توسط همه فریمورکها استفاده میشود. شامل سه فاز است. اول — تشخیص تغییر: file watcher (ساخته شده در IDE) یا سیستم فایل (FSNotify) تغییر در فایل .dart، .js، .tsx را ثبت میکند. دوم — کامپایل: کامپایلر افزایشی فقط فایل تغییر یافته را به نمایش میانی (kernel .dill برای Dart، HMR-module برای JS) تبدیل میکند. سوم — اعمال: کد جدید به دستگاه منتقل میشود و تعاریف قدیمی را در حافظه اپلیکیشن در حال اجرا جایگزین میکند.
جایگزینی داغ توابع (hot patching) — تکنیکی که در آن runtime اشارهگر تابع (function pointer) را در جدول متدهای مجازی جایگزین میکند. Dart VM از ClassTable — یک ساختار داخلی حاوی همه کلاسهای بارگذاری شده — استفاده میکند. در hot reload، VM کلاس را در ClassTable پیدا میکند و تعاریف توابع آن را با تعاریف جدید از فایل kernel جایگزین میکند. همه نمونههای موجود کلاس به طور خودکار رفتار جدید را دریافت میکنند.
// Flutter: callback reassemble برای مدیریت وضعیت پس از hot reload
class MyWidget extends StatefulWidget {
@override
State createState() => _MyState();
}
mixin ReloadAware on State {
@override
void reassemble() {
super.reassemble();
// بازنشانی کش یا دادهها پس از hot reload
clearCache();
}
}
در مثال، mixin ReloadAware متد reassemble() را بازنویسی میکند که Dart VM پس از hot reload روی هر شیء State فراخوانی میکند. توسعهدهنده میتواند کش را بازنشانی کند، منابع را دوباره مقداردهی اولیه کند یا مهاجرت وضعیت را انجام دهد. بدون این متد، دادههای قدیمی ممکن است در کش باقی بمانند و پس از بهروزرسانی ویجتها ناسازگاری ایجاد کنند.
جایگزینی داغ برای تغییراتی که نیاز به تخصیص مجدد حافظه برای فیلدهای جدید، تغییر نوع متغیر در کلاس، افزودن فیلدهای جدید در StatefulWidget، تغییر مقادیر enum یا پارامترهای generic دارند کار نمیکند. این تغییرات با اشیاء موجود در حافظه ناسازگار هستند — Dart VM نمیتواند فیلدها را در اشیاء از پیش تخصیص داده شده „بازچینی” کند. برای چنین مواردی راهاندازی مجدد داغ (hot restart) یا بازسازی کامل مورد نیاز است.
توسعه بومی Android و iOS به طور سنتی hot reload کامل ندارد. Android Studio با Android 11+ و AGP 4.2+ از Apply Changes پشتیبانی میکند: بهروزرسانی کد بدون راهاندازی مجدد اپلیکیشن. Apply Changes از طریق Android Runtime (ART) کار میکند — پیادهسازی متدها را در فایلهای dex در لحظه جایگزین میکند. با این حال Apply Changes محدود است: برای تغییرات منابع (layout.xml, drawable)، مانیفست و کتابخانههای بومی کار نمیکند.
Apple Previews (SwiftUI Preview) را در Xcode 15 (۲۰۲۳) معرفی کرد — این hot reload به معنای کلاسیک نیست. Previews بخش پیشنمایش را جدا از اپلیکیشن اصلی کامپایل میکند و نتیجه را در canvas Xcode نشان میدهد. هنگام ذخیره فایل، Preview در ۱–۳ ثانیه بهروزرسانی میشود، اما وضعیت اپلیکیشن حفظ نمیشود. برای پروژههای UIKit، hot reload از طریق ابزارهای شخص ثالث در دسترس است: InjectionIII (John Holdsworth) و SwiftHotReload.
Kotlin Multiplatform (KMP) از سال ۲۰۲۴ پشتیبانی آزمایشی hot reload را از JetBrains دریافت کرد. مکانیزم بر اساس Kotlin/Native runtime با جایگزینی توابع در فایل شیء (.klib) است. JetBrains Compose Multiplayer از پیادهسازی hot reload خود، مشابه Flutter استفاده میکند: کامپایل افزایشی و جایگزینی کلاسها در Kotlin/Native runtime. سرعت — ۱–۳ ثانیه، فقط برای تغییرات UI در دسترس است.
Apply Changes — مکانیزم Android Studio که از API ART runtime استفاده میکند. هنگام ذخیره کد، Android Studio تعیین میکند کدام کلاسها تغییر کردهاند و فایلهای dex آنها را از طریق adb به دستگاه ارسال میکند. ART پیادهسازی متدها را در اپلیکیشن در حال اجرا بدون توقف جایگزین میکند. Apply Changes در سه حالت کار میکند: Instant Run (جایگزینی سریع متد)، Swap (جایگزینی کلاس با بازآفرینی نمونهها) و Restart Activity (اگر تغییرات با وضعیت فعلی ناسازگار باشند).
سوالات متداول
Hot Reload کد را بدون راهاندازی مجدد اپلیکیشن بهروزرسانی میکند و وضعیت را حفظ میکند. Live Reload کل اپلیکیشن یا صفحه وب را در هنگام تغییر فایلها به طور کامل بارگذاری مجدد میکند. Live Reload در پیادهسازی سادهتر است، اما کندتر است و وضعیت را از دست میدهد. Flutter و React Native از hot reload استفاده میکنند، ابزارهای وب — از live reload.
Hot Reload برای تغییراتی که نیاز به تخصیص مجدد حافظه دارند (فیلدهای جدید کلاس)، تغییر ثابتهای استاتیک (static const)، تغییر نام ویجتها، تغییر enum یا پارامترهای generic کار نمیکند. این تغییرات با اشیاء موجود در حافظه Dart VM یا JavaScript runtime ناسازگار هستند.
بله، hot reload هم روی دستگاه فیزیکی و هم روی شبیهساز کار میکند. Flutter فایلهای kernel را از طریق USB (adb forward) یا Wi-Fi به دستگاه ارسال میکند. React Native از WebSocket از طریق metro bundler استفاده میکند. تأخیر روی دستگاه فیزیکی معمولاً ۱۰–۳۰٪ بیشتر از شبیهساز است.
Xcode Previews (از ۲۰۲۱) — معادل hot reload برای SwiftUI، اما با محدودیتها: پیشنمایش جداگانه کامپایل میشود، از ناوبری درون برنامه و وضعیتهای پیچیده پشتیبانی نمیکند. Apple hot reload رسمی برای iOS ارائه نمیدهد. ابزارهای شخص ثالث: InjectionIII و SwiftHotReload از Objective-C Runtime برای تزریق کد استفاده میکنند.
اگر پس از hot reload UI به درستی نمایش داده نمیشود: hot restart را انجام دهید. اگر مشکل در دادهها است — callback reassemble() را در Flutter یا useEffect cleanup در React Native بررسی کنید. برای مشکلات مداوم از Flutter Clean یا Reset Metro Cache استفاده کنید. اگر باگ فقط پس از reload تکرار میشود — این نشانه ناسازگاری تغییرات با وضعیت موجود است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید