
Flutter 3.47 mudou uma coisa que parecia impossível: Material e Cupertino saíram do SDK
A maior mudança desta versão talvez não seja visual — é arquitetural. E ela pode mudar a forma como o Flutter evolui daqui para frente.
Índice
Durante muito tempo, uma coisa parecia indissociável do Flutter:
import 'package:flutter/material.dart';
Quer usar Flutter? Você usa Material.
Quer Cupertino? Está dentro do SDK.
Só que isso acabou de mudar.
O Flutter 3.47 introduz oficialmente os pacotes independentes material_ui e cupertino_ui, ambos chegando à versão 1.0 no pub.dev.
E, olhando rapidamente, pode parecer apenas uma mudança de import.
Não é.
Essa mudança representa um passo importante na direção de um Flutter em que o core deixa de ser responsável pelo design system.
E isso abre algumas possibilidades bem interessantes para quem desenvolve Flutter profissionalmente.

O problema escondido dentro do material.dart
O Flutter sempre teve uma característica muito conveniente: grande parte da experiência de desenvolvimento vinha dentro do próprio SDK.
Você queria um botão?
ElevatedButton(
onPressed: () {},
child: const Text('Salvar'),
)
Um Scaffold?
Scaffold(
appBar: AppBar(
title: const Text('Minha aplicação'),
),
)
Tudo estava ali.
O problema aparece quando pensamos em velocidade de evolução.
Material e Cupertino faziam parte do próprio SDK. Portanto, suas mudanças estavam acopladas ao ciclo de lançamento do Flutter.
Na prática:
Para atualizar componentes de UI, você dependia de atualizar o Flutter.
Isso significa que uma correção ou novo componente de Material não poderia simplesmente ser publicado de forma independente.
O release do design system estava preso ao release do framework.
O Flutter 3.47 começa a quebrar exatamente esse acoplamento.
Material agora pode evoluir sem esperar pelo Flutter
A partir desta versão, você pode optar pelos pacotes independentes:
dependencies:
material_ui: ^1.0.0
cupertino_ui: ^1.0.0
A consequência mais interessante é que esses pacotes podem seguir seu próprio ciclo de releases.
O SDK pode continuar evoluindo em seu ritmo.
O Material pode evoluir em outro.
O Cupertino pode evoluir em outro.
E isso parece pequeno, mas muda bastante a arquitetura de evolução do ecossistema.
Imagine que amanhã exista uma nova API do Material que você queira utilizar.
Antes, seria natural pensar:
Preciso esperar uma nova versão do Flutter.
Agora a pergunta pode ser simplesmente:
Qual versão do
material_uieu preciso?
Essa diferença é enorme.
Mas e o código que já existe?
É aqui que a migração fica interessante.
Você não precisa sair substituindo manualmente centenas de imports.
O Flutter 3.47 traz uma ferramenta específica para isso:
dart fix --apply --code=migrate_design_widgets
Ela pode transformar imports como:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
em imports dos novos pacotes.
Por exemplo:
import 'package:material_ui/material_ui.dart';
Isso já mostra uma preocupação importante da equipe do Flutter:
desacoplar não significa quebrar o ecossistema inteiro de uma vez.
E existe um detalhe ainda mais importante
Imagine que sua aplicação já migrou para material_ui.
Mas uma dependência que você utiliza ainda está fazendo isso:
import 'package:flutter/material.dart';
Você teria um problema de compatibilidade.
Para resolver essa transição, o Flutter 3.47 introduz o:
MaterialUiCompatibilityBridge(...)
Um exemplo:
import 'package:material_ui/material_ui.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: (context, child) {
return MaterialUiCompatibilityBridge(
child: child!,
);
},
home: const HomeScreen(),
);
}
}
A ideia é permitir que o ecossistema faça essa migração progressivamente.
E isso é extremamente importante.
Porque frameworks não vivem apenas do código do framework.
Eles vivem de milhares de plugins, packages e aplicações construídas em cima dele.
Até as localizações foram desacopladas
Existe uma mudança que pode passar despercebida.
O flutter_localizations também entrou nesse processo.
Antes:
import 'package:flutter_localizations/flutter_localizations.dart';
localizationsDelegates: const [
GlobalCupertinoLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
Agora, utilizando o novo pacote:
import 'package:material_ui/material_ui.dart';
localizationsDelegates:
GlobalMaterialLocalizations.delegates,
O próprio pacote passa a fornecer os delegates necessários.
Parece apenas uma simplificação de API.
Mas existe uma ideia maior por trás:
se Material não pertence ao core, suas localizações também não deveriam pertencer.
Esse tipo de detalhe é o que mostra que estamos falando de uma mudança arquitetural, não apenas de reorganização de arquivos.
E aqui está a parte que mais me interessa
Existe uma frase escondida nessa mudança que merece atenção:
Flutter está criando as condições para um core de widgets neutro em relação a design systems.
Hoje, quando pensamos em Flutter, normalmente pensamos em:
Flutter
├── Material
└── Cupertino
Mas imagine um futuro mais próximo de:
Flutter Core
│
├── Material UI
├── Cupertino UI
├── Design System X
└── Design System Y
Isso muda a pergunta.
Em vez de:
Qual design system o Flutter fornece?
podemos começar a pensar:
Qual design system eu quero conectar ao Flutter?
E isso abre espaço para algo que sempre foi um pouco complicado no ecossistema: design systems completamente independentes do Material.
Flutter pode se tornar menos “opinionated”
Esse talvez seja o efeito mais interessante da mudança.
Durante anos, aprender Flutter significava inevitavelmente aprender Material.
Você podia construir algo completamente diferente, mas o framework continuava trazendo uma forte opinião sobre como uma aplicação deveria se comportar visualmente.
Agora, com os design systems vivendo como packages independentes, o core pode caminhar para uma posição mais neutra.
Isso não significa que Material vai desaparecer.
Muito pelo contrário.
Material continua sendo uma excelente opção.
A diferença é que ele deixa de precisar ser uma parte estrutural do framework para continuar sendo uma opção oficial do ecossistema.
Essa separação é saudável.
E o Impeller também mudou de fase
A separação dos design systems não é a única mudança arquitetural importante do Flutter 3.47.
Outra mudança chama bastante atenção:
Impeller agora é o renderer padrão no desktop.
Isso inclui:
- macOS
- Windows
- Linux
A ideia do Impeller é atacar um problema conhecido de renderização: o shader compilation jank.
Em engines tradicionais, determinados shaders podem precisar ser compilados durante a execução.
Isso pode resultar naquele comportamento estranho:
Primeira animação
↓
Shader precisa ser compilado
↓
Frame demora
↓
💥 Jank
O Impeller muda esse modelo ao compilar um conjunto fixo de shaders durante o build.
A consequência esperada?
A primeira execução da animação pode ser tão suave quanto as seguintes.
Não é simplesmente “um renderer novo”.
É uma tentativa de tornar a performance gráfica mais previsível.
Flutter Web também está olhando para o Wasm
Outro detalhe que merece atenção:
flutter build web --release --wasm
O Flutter está preparando o WebAssembly para se tornar o caminho padrão para aplicações web.
E existe uma consequência importante para quem possui código Flutter Web:
dart:html não é suportado nesse cenário.
A migração passa pelo novo modelo de interop:
package:web
Isso é mais um sinal de que o Flutter está tentando alinhar sua stack web com as tecnologias modernas da plataforma, em vez de depender indefinidamente das APIs legadas do navegador.
Widget Preview também deixou de ser experimento
Se você já trabalha em aplicações Flutter grandes, provavelmente conhece este problema:
Você quer ajustar um widget.
Mas para enxergá-lo precisa:
compilar aplicação
↓
iniciar aplicação
↓
navegar até a tela
↓
encontrar o widget
↓
alterar código
↓
repetir tudo
Widget Preview quer encurtar esse ciclo.
Agora a funcionalidade chegou ao stable.
A ideia é simples:
@Preview()
Widget userCardPreview() {
return const UserCard(
name: 'Wellington',
);
}
Você consegue visualizar e iterar sobre componentes individualmente, sem precisar iniciar toda a aplicação.
Para projetos grandes, isso pode ter um impacto enorme no ciclo de desenvolvimento.
E tem mais uma mudança que pode quebrar seu build
O Flutter 3.47 também atualiza a matriz de dependências Android.
Entre os requisitos indicados estão:
Java 17
Kotlin Gradle 2.4.0
AGP 9.1.0
Gradle 9.3.1
Além disso:
compileSdkVersion → API 36
targetSdkVersion → API 36
minSdkVersion → API 24
Então existe uma diferença importante entre:
Meu código Dart funciona no Flutter 3.47.
e:
Minha aplicação inteira está pronta para o Flutter 3.47.
São coisas diferentes.
Especialmente em aplicações que possuem plugins nativos, código Android/iOS personalizado ou dependências antigas.
Apple também está apertando o cerco
Para quem trabalha com Apple platforms, o Flutter 3.47 aumenta os requisitos mínimos:
| Plataforma | Antes | Flutter 3.47+ |
|---|---|---|
| iOS | 13 | 15 |
| macOS | 10.15 | 12 |
E existe outra mudança importante:
O iOS 27 passa a exigir o ciclo de vida baseado em UIScene para aplicações UIKit.
Em muitos projetos Flutter a migração será automática.
Mas se você possui código nativo customizado no AppDelegate, ou plugins que ainda dependem do ciclo antigo, pode precisar fazer a migração manualmente.
Swift Package Manager está cada vez mais importante
Outro número chamou minha atenção:
92 dos 100 principais plugins iOS já migraram para Swift Package Manager.
Isso é relevante porque CocoaPods está em modo de manutenção.
Ou seja, para quem mantém plugins Flutter, a mensagem é clara:
CocoaPods
↓
Swift Package Manager
Não é necessariamente uma migração que você precisa fazer hoje em toda aplicação.
Mas é definitivamente uma mudança que você deveria acompanhar.
Principalmente se sua equipe mantém plugins próprios.
Então, preciso migrar para Flutter 3.47 agora?
Não necessariamente.
Mas eu faria uma coisa diferente de simplesmente executar:
flutter upgrade
Eu trataria essa versão como uma oportunidade para revisar a arquitetura do projeto.
Começaria verificando:
1. Dependências
flutter pub outdated
Procure principalmente por plugins que ainda dependem de APIs antigas.
2. Android
Verifique:
Java
Gradle
AGP
Kotlin
compileSdk
3. iOS
Principalmente se você possui:
AppDelegatecustomizado- código nativo
- plugins internos
- integrações com SDKs nativos
4. Flutter Web
Se você possui uma aplicação web, teste:
flutter build web --release --wasm
Mesmo que você ainda não vá colocar Wasm em produção.
Testar agora é muito mais barato do que descobrir incompatibilidades quando isso se tornar o padrão.
5. Design System
E finalmente:
olhe para seus imports.
Se seu projeto possui centenas de:
package:flutter/material.dart
não significa que você precisa migrar tudo imediatamente.
Mas vale entender como essa nova arquitetura afetará seu projeto e as dependências que você utiliza.
A mudança mais importante não está em nenhuma API
Flutter 3.47 traz Impeller no desktop.
Wasm está avançando.
Widget Preview chegou ao stable.
SwiftPM está ganhando espaço.
O suporte às novas versões da Apple está chegando.
Tudo isso é importante.
Mas, para mim, a mudança mais interessante é outra:
Flutter começou a separar o framework do design system.
E isso muda a direção do projeto.
Durante anos, Flutter foi um framework que trazia consigo uma visão muito clara de UI.
Agora ele começa a caminhar para algo mais modular:
Flutter Core
│
┌──────────┼──────────┐
↓ ↓ ↓
Material Cupertino Outros
│ │ │
releases releases releases
próprios próprios próprios
É uma mudança que talvez passe despercebida por quem está apenas procurando novidades de widgets.
Mas para quem pensa em arquitetura, evolução de frameworks e design systems, ela é muito maior.
O Flutter não está apenas adicionando funcionalidades.
Está começando a desacoplar as próprias responsabilidades que construíram o framework.
E essa talvez seja uma das mudanças mais importantes para observar nas próximas versões.
Para experimentar
Se você quer começar a testar a nova versão:
flutter upgrade
E, se quiser experimentar o caminho Wasm:
flutter build web --release --wasm
O mais interessante, porém, não é simplesmente atualizar.
É observar para onde o Flutter está indo.
Porque algumas mudanças parecem apenas uma alteração de import hoje.
Até que você percebe que elas estão mudando a arquitetura do framework.



