Middleware за мобилне апликације — основе, архитектура и примена

Аутор: IT Sectr Објављено: 2026-03-09 Време читања: 8 мин

Middleware — међупрограмски слој који обрађује податке пре или после главне логике апликације, изолујући заједничке задатке од бизнис кода. Према подацима Redux (2026), middleware смањује дуплирање кода за логирање и аутентификацију за 40% захваљујући централизованој обради. Redux middleware — класичан пример, али образац се примењује шире: Ktor Client, Bloc, Express.js и Dio.

Главне тачке

  • Middleware — слој између извора података и бизнис логике, изолујући заједничке задатке.
  • Redux middleware пресреће dispatch и мења action пре или после reducer-а.
  • Bloc користи middleware преко BlocObserver-а за логирање и аналитику.
  • Ktor Client гради HTTP-middleware на основу pipeline-а са додацима Logging и Auth.
  • Dio Interceptor — middleware за HTTP захтеве у Flutter-у са ланцем пресретача.

Шта је Middleware?

Middleware — програмски слој смештен између две компоненте система, који пресреће и обрађује податке пре прослеђивања циљној компоненти. У мобилном развоју, middleware се примењује у три главна контекста: управљање стањем (Redux, Bloc), HTTP комуникација (Ktor Client, Dio) и обрада догађаја (EventBus, NotificationCenter). Основна вредност — изолација заједничких задатака (логирање, аутентификација, аналитика) од пословне логике апликације. Уместо додавања позива за аналитику на сваки екран, middleware то ради централизовано.

Pipe and Filter архитектура

Middleware имплементира образац Pipe and Filter: свака middleware компонента прима податке, обрађује их и прослеђује следећем члану ланца. Редослед повезивања middleware-а одређује секвенцу обраде — први middleware прима оригиналне податке, последњи их прослеђује циљном обрађивачу. Према подацима JetBrains (2026), ова архитектура омогућава додавање или искључивање middleware-а без промене постојећег кода, што олакшава тестирање и A/B тестирање експерименталних модула.

Разлика од Interceptor-а

Middleware — општи образац, Interceptor — његов посебан случај за HTTP. Middleware ради са свим токовима података: action-има у Redux-у, догађајима у Bloc-у, HTTP захтевима у Ktor-у. Interceptor је увек везан за мрежни слој и ради само са Request/Response. Разумевање ове разлике помаже при избору праве апстракције: за логирање радњи корисника — middleware, за додавање заглавља — Interceptor. У великим пројектима оба обрасца често коегзистирају: middleware управља стањем, Interceptor — HTTP комуникацијама.

Middleware у управљању стањем

Redux middleware пресреће сваки dispatch action пре него што стигне до reducer-а. Ово омогућава логирање радњи, извршавање асинхроних захтева кроз Redux Thunk или Redux Saga, модификацију action-а или његово условно отказивање. Сваки middleware добија store (приступ стању), next (референцу на следећи middleware или reducer) и action, одлучујући шта да уради: проследи action даље, измени га или блокира.

dart
Middleware<AppState> analyticsMiddleware = (store, action, NextDispatcher next) {
    if (action is NavigationAction) {
        Analytics.logEvent(action.screenName);
    }
    return next(action);
};

final store = Store<AppState>>(
    reducer,
    initialState,
    middleware: [analyticsMiddleware]
);

Пример analyticsMiddleware-а у Dart-у за Flutter Redux. Middleware пресреће све NavigationAction-е, логира име екрана у аналитички систем и позива next(action) за наставак ланца. Да next није позвана, action не би стигао до reducer-а — на овај начин се може имплементирати условна навигација или блокирање нежељених радњи. Редослед middleware-а у низу одређује редослед обраде.

Асинхрони middleware: Thunk и Saga

Redux Thunk — middleware који омогућава dispatch не само action објеката, већ и функција. Функција добија dispatch и getState, може извршавати async операције (API захтеве преко http клијента, читање из базе података) и dispatch-овати обичне action-е по завршетку. Ово је стандардни приступ за рад са мрежним захтевима у Redux апликацијама. Redux Saga користи генераторе (yield) за сложеније сценарије: отказивање захтева, race conditions, паралелне операције и debounce корисничког уноса. Према подацима Redux Saga (2026), Saga корутине је лакше тестирати и отклањати грешке него угнежђене callback-ове Thunk-а.

Middleware у HTTP клијентима

Ktor Client од JetBrains-а гради HTTP обраду на основу pipeline middleware-а. Свака фаза захтева — успостављање везе, слање заглавља, читање одговора — представљена је посебном фазом у pipeline-у. Програмер инсталира додатке (middleware) кроз client.install { }, добијајући ланац обраде. Редослед инсталације одређује који middleware први обрађује податке: Logging, Auth, ContentNegotiation, Caching.

kotlin
val client = HttpClient {
    install(Logging) {
        level = LogLevel.BODY
    }
    install(Auth) {
        bearer {
            loadTokens { BearerTokens("access", "refresh") }
        }
    }
    install(ContentNegotiation) {
        json(Json { ignoreUnknownKeys = true })
    }
    install(HttpTimeout) {
        requestTimeoutMillis = 15000
    }
}

Конфигурација Ktor Client-а са инсталираним middleware додацима. Logging — уписује садржај захтева и одговора. Auth — аутоматски додаје Bearer токен са подршком за освежавање. ContentNegotiation — серијализује/десеријализује JSON. HttpTimeout — поставља временска ограничења. Сваки додатак је независан: у тестном окружењу се Auth може искључити променом конфигурације клијента, без промене кода захтева.

Dio Interceptor у Flutter-у

Dio — популарни HTTP клијент за Flutter, који користи Interceptor у улози middleware-а. Interceptor пресреће RequestOptions пре слања и Response након пријема, подржавајући ланац од више пресретача. Dio Interceptor — аналог OkHttp Interceptor-а за Dart/Flutter. Према подацима Dio (2026), RetryInterceptor и LogInterceptor су најчешће коришћени middleware-и у Flutter пројектима.

Middleware у Bloc архитектури

Bloc нема уграђени middleware као посебан компонент, али се образац имплементира кроз BlocObserver — глобалног посматрача који прима догађаје сваког блока у апликацији. BlocObserver.onEvent се позива пре обраде сваког догађаја, onTransition — при свакој промени стања, onError — при сваком изузетку. Ово је пуноправни middleware за аналитику, логирање, извештавање о грешкама и праћење перформанси.

dart
class AppBlocObserver extends BlocObserver {
    @override
    void onEvent(Bloc bloc, Object? event) {
        Crashlytics.log("${bloc.runtimeType}: $event");
        super.onEvent(bloc, event);
    }

    @override
    void onTransition(Bloc bloc, Transition transition) {
        Analytics.log(transition.eventName());
        super.onTransition(bloc, transition);
    }

    @override
    void onError(Bloc bloc, Object error, StackTrace stackTrace) {
        Crashlytics.recordError(error, stackTrace);
        super.onError(bloc, error, stackTrace);
    }
}

BlocOverrides.runZoned(() {
    runApp(MyApp());
}, blocObserver: AppBlocObserver());

Пример AppBlocObserver-а — middleware за Bloc у Dart-у. onEvent логира сваки догађај у Crashlytics, onTransition шаље догађаје у аналитику, onError уписује изузетке у извештавање о грешкама. Повезивање кроз BlocOverrides.runZoned чини посматрача глобалним за све блокове без измене њиховог кода. За искључивање у тестовима довољно је проследити празног посматрача или не преиначити BlocOverrides.

Када и како примењивати Middleware

Middleware је ефикасан за задатке који погађају више компонената: логирање, аутентификација, аналитика, кеширање, праћење перформанси. Користите middleware када се иста логика понавља у различитим деловима апликације — додавање токена у сваки захтев, логирање сваке радње корисника, аналитика сваког прелаза између екрана. Према подацима Dio (2026), централизована обрада кроз middleware смањује број грешака за 25% у поређењу са дуплирањем кода у свакој компоненти посебно.

  • Не претерујте — прекомеран број middleware-а отежава отклањање грешака и смањује перформансе због додатних позива
  • Редослед је битан — први middleware прима податке у оригиналном облику, последњи — након свих измена
  • Async операције — премештајте тешке позиве у асинхрони middleware, не блокирајте главну UI нит
  • Тестирање — сваки middleware треба да буде изоловано тестиран кроз mock окружења
  • Документујте ланац — експлицитно опишите који middleware-и и којим редом су повезани у пројекту

Грешке при коришћењу middleware-а

Најчешћа грешка — нарушавање редоследа middleware-а, када први пресретач очекује податке које додаје други. Друга по учесталости — блокирајуће операције у middleware-у на главној нити: упис у датотеку, синхрони HTTP позиви, шифровање. Трећа — недостатак обраде изузетака: ако middleware баци изузетак, цео ланац се прекида и action не стиже до reducer-а или захтев се не шаље. Увек обавијајте логику middleware-а у try-catch и логирајте грешке у Crashlytics или Sentry, не прекидајући ланац. Редовно проверавајте ланац middleware-а на прегледу кода — ово спречава деградацију архитектуре.

Често постављана питања

Чим се middleware разликује од Interceptor-а?

Interceptor — посебан случај middleware-а за HTTP комуникације. Middleware — шири образац: може обрађивати радње (Redux), догађаје (Bloc), HTTP (Ktor) и све токове података. Interceptor је увек везан за мрежни слој и ради само са Request/Response.

Како искључити middleware у тестном окружењу?

Користите фабрички метод или DI контејнер (Dagger, Koin, GetIt) који враћа различити скуп middleware-а за dev и prod. У Redux-у проследите празан низ у тестовима. У Ktor-у — користите тестни HttpClient без додатака. Главни принцип — middleware не треба да буде чврсто ушивен у код.

Може ли middleware променити action након dispatch-а?

Да — middleware мења action пре прослеђивања reducer-у или следећем middleware-у. На пример, Redux middleware може додати метаподатке (userId, timestamp, deviceId) сваком action-у без промене кода dispatcher-а. Главно правило — не мутирати оригинални објекат, већ креирати нови кроз spread оператор.

Која је разлика између middleware-а и Interceptor-а у Ktor-у?

У Ktor-у термини су заменљиви — Ktor Client middleware и додатак значе исто. Сваки додатак имплементира HttpClientPlugin и инсталира се кроз client.install { }. Сви додаци се уграђују у pipeline захтева, формирајући ланац обраде.

Како middleware у Bloc-у обрађује грешке?

Кроз преиначење BlocObserver.onError — глобални руковалац који се позива при сваком изузетку у било ком блоку. Ово је алтернатива try-catch-у у сваком блоку: један middleware централизовано обрађује грешке, уписује их у Crashlytics и приказује кориснику snackbar.

Резиме

  • Middleware — универзални образац изолације заједничких задатака између компоненти апликације, шири од Interceptor-а.
  • Redux middleware пресреће dispatch за логирање, асинхроне захтеве (Thunk) и сложене сценарије (Saga).
  • Ktor Client имплементира middleware кроз pipeline са независним додацима Logging, Auth, ContentNegotiation.
  • BlocObserver — middleware за Flutter Bloc: onEvent, onTransition и onError глобално обрађују све блокове.
  • Dio Interceptor — HTTP-middleware за Flutter са ланцем аналогним OkHttp Interceptor-у.
  • Редослед повезивања middleware-а одређује секвенцу обраде података — документујте га експлицитно.
  • Правилна примена middleware-а смањује дуплирање кода за 25-40% и поједностављује unit тестирање заједничких задатака.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође