Hot Reload — технологија која омогућава ажурирање кода радне мобилне апликације без поновног покретања и губитка тренутног стања. Програмер мења изворни код — после секунде измене се приказују на екрану уређаја или емулатора. Ово је кључна карактеристика Flutter и React Native, која радикално убрзава итерације развоја: време циклуса измена-преглед се смањује са 5–10 секунди (прекомпилација) на 300–500 милисекунди. Према Flutter Documentation, 2025, hot reload врши инкременталну компилацију измењеног кода и шаље ажурирање у Dart VM.
Главно
Hot Reload — механизам развоја при којем се изворни код мења и примењује на већ покренуту апликацију без њеног заустављања. Програмер уређује датотеку, чува је и после 0.3–2 секунде ажурирани интерфејс се приказује на екрану. Стање апликације (бројачи, позиција померања, унети подаци) се чува — програмер не губи контекст.
Концепт hot reload-а настао је у раним веб алатима (LiveReload, 2010) и адаптиран је за мобилни развој од стране Flutter (2017) и React Native (2015). Данас је hot reload обавезна функција савремених мобилних оквира, поред debug конфигурације и профилисања. Без hot reload-а развој UI-ја се сматра неефикасним: сваки преглед измене захтева 10–30 секунди за прекомпилацију и покретање.
Технички, 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 позива reassemble() за све State објекте, а build() се поново покреће са ажурним кодом и сачуваним стањем.
Када hot reload не ради: ако је измењена статичка променљива иницијализације (static const), глобална променљива, main(), декларација класе enum/mixin, код у @override initState(). У овим случајевима је потребан Hot Restart. Према подацима Flutter Team (2025), hot reload је успешан у 85–90% случајева; 10–15% измена захтева потпуно поновно покретање.
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 преноси само разлику измењеног модула — не цео бандл. React Native користи React Fast Refresh, развијен од стране React тима (Dan Abramov, 2019): генерише нови рендер за компоненту, али чува hook стања и props ако се потпис компоненте није променио.
Fast Refresh не ради при промени: export компоненте, hook-ова (useEffect, useMemo), модуларних зависности и изворних модула (Java/Objective-C). За такве измене је потребан Reload (потпуно поновно учитавање JS бандла) или Rebuild (прекомпилација изворног кода). Време fast refresh-а — 200–800 ms, потпуно reload — 2–5 секунди.
Hot Reload и Hot Restart — два режима ажурирања кода са различитим сценаријима употребе. Hot Reload је погодан за измене UI-ја (стилови, распоред, боје, текстови), када се структура класа и тип стања не мењају. Hot Restart је неопходан при промени потписа метода, додавању нових виџета/компоненти у коренско стабло, промени initState и изворних модула.
| Карактеристика | Hot Reload | Hot Restart |
|---|---|---|
| Брзина | 0.3–2 секунде | 2–10 секунди |
| Чување стања | Да (променљиве, 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-ом је већа за 40–60% у поређењу са потпуним прекомпилацијама (подаци JetBrains Developer Survey 2024).
Ињекција кода (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: reassemble callback за управљање стањем након 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 позива на сваком State објекту након hot reload-а. Програмер може да ресетује кеш, поново иницијализује ресурсе или изврши миграцију стања. Без овог метода стари подаци могу остати у кешу и изазвати неусаглашеност након ажурирања виџета.
Врућа замена не ради за измене које захтевају прерасподелу меморије за нова поља, промену типа променљиве у класи, додавање нових поља у 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 (2023) — ово није hot reload у класичном смислу. Previews компилира прегледну секцију одвојено од главне апликације и приказује резултат у Xcode canvas-у. При чувању датотеке, Preview се ажурира за 1–3 секунде, али стање апликације се не чува. За UIKit пројекте, hot reload је доступан путем алата трећих страна: InjectionIII (John Holdsworth) и SwiftHotReload.
Kotlin Multiplatform (KMP) је од 2024. добио експерименталну подршку за hot reload од JetBrains-а. Механизам се заснива на Kotlin/Native runtime-у са заменом функција у објектној датотеци (.klib). JetBrains Compose Multiplayer користи сопствену имплементацију hot reload-а, сличну Flutter-у: инкрементална компилација и замена класа у Kotlin/Native runtime-у. Брзина — 1–3 секунде, доступно само за UI измене.
Apply Changes — механизам Android Studio-а који користи ART runtime API. При чувању кода, 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-а. Кашњење на физичком уређају је обично 10–30% веће него на емулатору.
Xcode Previews (од 2021) — аналог hot reload-а за SwiftUI, али са ограничењима: преглед се компилира одвојено, не подржава навигацију кроз апликацију и сложена стања. Apple не пружа званични hot reload за iOS. Алати трећих страна: InjectionIII и SwiftHotReload користе Objective-C Runtime за ињекцију кода.
Ако се након hot reload-а UI приказује неисправно: извршите hot restart. Ако је проблем у подацима — проверите reassemble() callback у Flutter-у или useEffect cleanup у React Native-у. За сталне проблеме користите Flutter Clean или Reset Metro Cache. Ако се баг понавља само након reload-а — то је знак некомпатибилности измена са постојећим стањем.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође