Middleware para aplicações móveis — fundamentos, arquitetura e aplicação

Autor: IT Sectr Publicado: 2026-03-09 Tempo de leitura: 8 min

Middleware é uma camada de software intermediária que processa dados antes ou depois da lógica principal da aplicação, isolando preocupações transversais do código de negócio. Segundo Redux (2026), o middleware reduz a duplicação de código de logging e autenticação em 40% através do processamento centralizado. Redux middleware é um exemplo clássico, mas o padrão é usado mais amplamente: Ktor Client, Bloc, Express.js e Dio.

Principais pontos

  • Middleware é uma camada entre fontes de dados e lógica de negócio, isolando preocupações transversais.
  • Redux middleware intercepta dispatch e modifica uma ação antes ou depois do reducer.
  • Bloc usa middleware via BlocObserver para logging e análise.
  • Ktor Client constrói HTTP-middleware baseado em pipeline com plugins Logging e Auth.
  • Dio Interceptor é middleware para requisições HTTP em Flutter com uma cadeia de interceptadores.

O que é Middleware?

Middleware é uma camada de software localizada entre dois componentes do sistema, que intercepta e processa dados antes de passá-los ao componente de destino. No desenvolvimento móvel, o middleware é usado em três contextos principais: gerenciamento de estado (Redux, Bloc), comunicações HTTP (Ktor Client, Dio) e manipulação de eventos (EventBus, NotificationCenter). O valor fundamental é o isolamento de preocupações transversais (logging, autenticação, análise) da lógica de domínio da aplicação. Em vez de adicionar chamadas de análise a cada tela, o middleware o faz centralizadamente.

Arquitetura Pipe and Filter

O middleware implementa o padrão Pipe and Filter: cada componente middleware recebe dados, processa-os e passa ao próximo elo da cadeia. A ordem de conexão do middleware determina a sequência de processamento — o primeiro middleware recebe dados brutos, o último os passa ao manipulador de destino. Segundo JetBrains (2026), esta arquitetura permite adicionar ou remover middleware sem alterar o código existente, simplificando testes e testes A/B de módulos experimentais.

Diferença do Interceptor

Middleware é um padrão geral, Interceptor é seu caso especial para HTTP. Middleware funciona com qualquer fluxo de dados: ações no Redux, eventos no Bloc, requisições HTTP no Ktor. Interceptor está sempre vinculado à camada de rede e só trabalha com Request/Response. Entender essa diferença ajuda a escolher a abstração correta: para registrar ações do usuário — middleware, para adicionar cabeçalhos — Interceptor. Em projetos grandes, ambos os padrões geralmente coexistem: middleware gerencia o estado, Interceptor lida com comunicações HTTP.

Middleware no gerenciamento de estado

Redux middleware intercepta cada ação dispatch antes que ela chegue ao reducer. Isso permite registrar ações, realizar requisições assíncronas via Redux Thunk ou Redux Saga, modificar uma ação ou cancelá-la condicionalmente. Cada middleware recebe store (acesso ao estado), next (referência ao próximo middleware ou reducer) e action, decidindo o que fazer: passar a ação, modificá-la ou bloqueá-la.

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]
);

Exemplo de analyticsMiddleware em Dart para Flutter Redux. O middleware intercepta todos os NavigationAction, registra o nome da tela no sistema de análise e chama next(action) para continuar a cadeia. Se next não fosse chamada, a ação não chegaria ao reducer — assim é possível implementar navegação condicional ou bloquear ações indesejadas. A ordem do middleware no array determina a sequência de processamento.

Middleware assíncrono: Thunk e Saga

Redux Thunk é um middleware que permite despachar não apenas objetos de ação mas também funções. A função recebe dispatch e getState, pode realizar operações assíncronas (requisições de API via cliente HTTP, leitura de BD) e despachar ações normais ao finalizar. Esta é a abordagem padrão para requisições de rede em aplicações Redux. Redux Saga usa geradores (yield) para cenários mais complexos: cancelamento de requisições, condições de corrida, operações paralelas e debounce de entrada do usuário. Segundo Redux Saga (2026), as corrotinas Saga são mais fáceis de testar e depurar que os callbacks aninhados do Thunk.

Middleware em clientes HTTP

Ktor Client da JetBrains constrói o processamento HTTP baseado em pipeline middleware. Cada etapa da requisição — configuração de conexão, envio de cabeçalhos, leitura de resposta — é representada por uma fase separada no pipeline. O desenvolvedor instala plugins (middleware) via client.install { }, obtendo uma cadeia de processamento. A ordem de instalação determina qual middleware processa dados primeiro: 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
    }
}

Configuração do Ktor Client com plugins middleware instalados. Logging — escreve o corpo da requisição e resposta. Auth — adiciona automaticamente o token Bearer com suporte a refresh. ContentNegotiation — serializa/desserializa JSON. HttpTimeout — define timeouts. Cada plugin é independente: em ambiente de teste pode-se desabilitar Auth substituindo a configuração do cliente sem alterar o código das requisições.

Dio Interceptor no Flutter

Dio é um cliente HTTP popular para Flutter, que usa Interceptor como middleware. Interceptor intercepta RequestOptions antes de enviar e Response após receber, suportando uma cadeia de múltiplos interceptadores. Dio Interceptor é análogo ao OkHttp Interceptor para Dart/Flutter. Segundo Dio (2026), RetryInterceptor e LogInterceptor são os middleware mais usados em projetos Flutter.

Middleware na arquitetura Bloc

Bloc não tem middleware integrado como componente separado, mas o padrão é implementado via BlocObserver — um observador global que recebe eventos de cada bloco na aplicação. BlocObserver.onEvent é chamado antes de processar cada evento, onTransition em cada transição de estado, onError em cada exceção. É um middleware completo para análise, logging, relatórios de falhas e monitoramento de desempenho.

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());

Exemplo de AppBlocObserver — middleware para Bloc em Dart. onEvent registra cada evento no Crashlytics, onTransition envia eventos para análise, onError escreve exceções no relatório de falhas. A conexão via BlocOverrides.runZoned torna o observador global para todos os blocos sem alterar seu código. Para desabilitar em testes, basta passar um observador vazio ou não sobrescrever BlocOverrides.

Quando e como usar Middleware

Middleware é eficaz para tarefas que afetam muitos componentes: logging, autenticação, análise, cache, monitoramento de desempenho. Use middleware quando a mesma lógica se repete em diferentes partes da aplicação — adicionar um token a cada requisição, registrar cada ação do usuário, análise de cada transição de tela. Segundo Dio (2026), o processamento centralizado via middleware reduz bugs em 25% comparado a duplicar código em cada componente separadamente.

  • Não abuse — middleware em excesso complica a depuração e reduz o desempenho devido a chamadas adicionais
  • A ordem importa — o primeiro middleware recebe dados em sua forma original, o último após todas as modificações
  • Operações assíncronas — transfira chamadas pesadas para middleware assíncrono sem bloquear a thread principal da UI
  • Testabilidade — cada middleware deve ser testado isoladamente via ambientes mock
  • Documente a cadeia — descreva explicitamente quais middleware estão conectados e em que ordem no projeto

Erros comuns ao usar middleware

O erro mais frequente é ordem incorreta do middleware, quando o primeiro interceptador espera dados que o segundo adiciona. O segundo erro mais comum são operações bloqueantes em middleware na thread principal: escrita de arquivos, chamadas HTTP síncronas, criptografia. O terceiro é falta de tratamento de exceções: se um middleware lançar uma exceção, toda a cadeia quebra e a ação não chegará ao reducer ou a requisição não será enviada. Sempre envolva a lógica do middleware em try-catch e registre erros no Crashlytics ou Sentry sem quebrar a cadeia. Revise regularmente a cadeia de middleware durante revisões de código — isso previne a degradação da arquitetura.

Perguntas frequentes

Qual a diferença entre middleware e Interceptor?

Interceptor é um caso especial de middleware para comunicações HTTP. Middleware é um padrão mais amplo: pode manipular ações (Redux), eventos (Bloc), HTTP (Ktor) e qualquer fluxo de dados. Interceptor está sempre vinculado à camada de rede e só trabalha com Request/Response.

Como desabilitar middleware em ambiente de teste?

Use um método fábrica ou contêiner DI (Dagger, Koin, GetIt) que retorne um conjunto diferente de middleware para dev e prod. No Redux, passe um array vazio nos testes. No Ktor, use um HttpClient de teste sem plugins. O princípio principal é que o middleware não deve estar hardcoded.

O middleware pode modificar uma ação após o dispatch?

Sim — o middleware modifica a ação antes de passá-la ao reducer ou ao próximo middleware. Por exemplo, Redux middleware pode adicionar metadados (userId, timestamp, deviceId) a cada ação sem alterar o código do dispatcher. A regra principal é não mutar o objeto original mas criar um novo através do operador spread.

Qual a diferença entre middleware e Interceptor no Ktor?

No Ktor, os termos são intercambiáveis — Ktor Client middleware e plugin significam a mesma coisa. Cada plugin implementa HttpClientPlugin e é instalado via client.install { }. Todos os plugins são incorporados ao pipeline da requisição, formando uma cadeia de processamento.

Como o middleware no Bloc trata erros?

Sobrescrevendo BlocObserver.onError — um manipulador global chamado em cada exceção em qualquer bloco. É uma alternativa ao try-catch em cada bloco: um middleware centralizado trata erros, escreve-os no Crashlytics e exibe um snackbar ao usuário.

Resumo

  • Middleware é um padrão universal para isolar preocupações transversais entre componentes da aplicação, mais amplo que Interceptor.
  • Redux middleware intercepta dispatch para logging, requisições assíncronas (Thunk) e cenários complexos (Saga).
  • Ktor Client implementa middleware via pipeline com plugins independentes Logging, Auth, ContentNegotiation.
  • BlocObserver é middleware para Flutter Bloc: onEvent, onTransition e onError tratam todos os blocos globalmente.
  • Dio Interceptor é HTTP-middleware para Flutter com uma cadeia análoga ao OkHttp Interceptor.
  • A ordem de conexão do middleware determina a sequência de processamento de dados — documente-a explicitamente.
  • O uso adequado do middleware reduz a duplicação de código em 25-40% e simplifica testes unitários de preocupações transversais.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também