Na aula anterior, criamos nosso primeiro projeto Flutter. Ele é muito simples, contendo apenas um botão que incrementa um número ao ser clicado. Veja abaixo a estrutura de pastas deste projeto.
Estrutura de pastas do projeto

Você verá diversas pastas e arquivos como android, web, windows, lib, test e outros. Onde fica o código fonte que você vai escrever? No android? No windows? Na verdade não, fica na pasta lib. Ao abrir a lib, você verá um arquivo main.dart.

A pasta lib vai guardar todo o seu código fonte daqui em diante. Você vai programar em Dart, não em Java nem C++. O Flutter usa a linguagem Dart. Mas por que existem pastas como android, web e windows?
A explicação é simples: o Flutter consegue compilar para aplicativos de várias plataformas graças a essas pastas.
O Flutter é um framework com um único código Dart que roda em múltiplas plataformas. A pasta lib contém o código de negócio compartilhado entre todas as plataformas que você escreve. Já as pastas android / windows / web / macos / linux são projetos nativos de hospedagem de cada plataforma, responsáveis por embutir o Flutter no sistema correspondente para execução.
1. Pasta android
Trata-se do projeto nativo da plataforma Android
Ele fornece o contêiner de execução do app Android e hospeda o motor de renderização do Flutter. Todas as configurações de baixo nível relacionadas ao Android são feitas aqui: permissões do app, ícones, nome de pacote e mais. Ou seja, aqui você configura elementos exclusivos do Android e consegue chamar APIs nativas do sistema (câmera, bluetooth, notificações, localização etc.)
2. Pasta windows
É o projeto nativo para desktop Windows
Trata-se de um projeto nativo C++ Win32 que cria janelas do Windows e inicializa o motor de renderização Skia. Skia é a biblioteca gráfica do Google, utilizada pelo Flutter para renderizar janelas e todos os controles em apps de desktop.
Dentro da pasta windows ficam as configurações de baixo nível do software de desktop Windows: tamanho da janela, barra de título, ícones, bandeja do sistema (o ícone no canto inferior direito do Windows).
No final você consegue empacotar o projeto em arquivos exe ou msix para publicar na Microsoft Store, entre outras opções.
3. Pasta web
Projeto de página web estática (HTML/JS/CSS) com o ponto de entrada web index.html. Seu código Dart será compilado em recursos para web.
Permite configurar título da página, ícones, recursos estáticos e rotas. Ao compilar, gera arquivos HTML/CSS/JS prontos para hospedar em um servidor e abrir em navegadores.
Outras pastas
Não usamos iOS, macOS nem Linux neste exemplo, pois não marcamos essas opções na criação do projeto, por isso essas pastas não aparecem aqui. Mas o funcionamento delas é igual.
ios: Projeto nativo Xcode para iOS da Apple, usado para empacotar arquivos ipa e lançar no iPhone
macos: Projeto nativo Cocoa para desktop macOS, cliente para computadores Mac
linux: Projeto de desktop Linux baseado em GTK
No canto superior direito do Android Studio você seleciona diferentes plataformas para compilar versões distintas do aplicativo. Você também pode usar a linha de comando diretamente; na verdade, ao escolher uma plataforma e clicar no triângulo verde no Android Studio, ele executa comandos do Flutter nos bastidores.
# Rodar versão Android, lê configurações da pasta android
flutter run -d android
# Rodar desktop Windows, lê o projeto C++ da pasta windows
flutter run -d windows
# Rodar versão web, lê o html da pasta web
flutter run -d chromeCode language: PHP (php)

Abra o arquivo runner / main.php da pasta windows
#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
#include <windows.h>
#include "flutter_window.h"
#include "utils.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) {
// Attach to console when present (e.g., 'flutter run') or create a
// new console when running with a debugger.
if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
CreateAndAttachConsole();
}
// Initialize COM, so that it is available for use in the library and/or
// plugins.
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
flutter::DartProject project(L"data");
std::vector<std::string> command_line_arguments =
GetCommandLineArguments();
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.Create(L"myproject", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);
::MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::CoUninitialize();
return EXIT_SUCCESS;
}
Code language: PHP (php)
Se você compilar para o Windows Desktop, esse main.cpp é o ponto de entrada real do programa: esse arquivo C++ é executado primeiro, depois o seu lib/main.dart.
Da mesma forma, ao abrir a pasta android você verá uma estrutura quase idêntica aos projetos Android desenvolvidos com Kotlin ou Java.

Também contém a pasta src, o arquivo AndroidManifest.xml, MainActivity e outros elementos familiares para quem desenvolve apps Android. De fato, ao criar um app Android com Flutter, a execução começa por essa pasta android.
Da mesma maneira, ao abrir a pasta web você encontra o ponto de entrada web index.html

Arquivos Dart
O arquivo main.dart dentro da lib será o local onde você fará a maior parte do desenvolvimento. Você pode criar subpastas e adicionar outros arquivos Dart dentro da lib.
Abra o main.dart
// Importar biblioteca de componentes Material
import 'package:flutter/material.dart';
// Função de entrada do programa
void main() {
runApp(const MyApp());
}
// Componente raiz do aplicativo (sem estado)
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// Configuração global do tema
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
// Página inicial
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
// Página inicial (componente com estado)
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// Parâmetro de título da página
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// Classe de gerenciamento de estado da página inicial
class _MyHomePageState extends State<MyHomePage> {
// Variável contador
int _counter = 0;
// Método para incrementar o contador
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
// Modelo base de layout de página
return Scaffold(
// Barra de navegação superior
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
// Conteúdo principal da página
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter', // Exibe a variável numérica acima
style: Theme.of(context).textTheme.headlineMedium, // Estilo do texto
),
],
),
),
// Botão flutuante inferior direito: onPressed executa _incrementCounter, tooltip é o texto de dica, child configura o ícone
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Code language: JavaScript (javascript)
1. Parte de entrada
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
Code language: JavaScript (javascript)
- Importa o Material, o conjunto oficial de componentes UI do Google (botões, telas, textos etc.). A Apple tem seu próprio framework de interface.
mainé o único ponto de entrada de um programa Dart;runApp()inicializa o app e monta o componente raizMyApp
2. MyApp: Componente raiz global
Ele é um StatelessWidget (componente sem estado), vamos explicar depois, basta saber isso por enquanto.
class MyApp extends StatelessWidget {
const MyApp({super.key});
// Componente raiz do seu aplicativo
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
Code language: JavaScript (javascript)
- Configurações globais: Nome do app, tema geral, página inicial
MaterialApp: Contêiner de aplicativo com estilo Material, gerencia rotas, temas e títulos de forma unificadahomedefine a página padrão ao abrir o app:MyHomePage
3. MyHomePage: Página inicial
Página exibida por padrão ao abrir a janela ou o app, é um StatefulWidget (componente com estado), detalharemos depois.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}Code language: JavaScript (javascript)
- Contém dados variáveis (o número do contador), por isso usamos um componente com estado
- Recebe o parâmetro
titlede fora e é lido viawidget.titlena classe de estado - Deve ser acompanhado da classe
_MyHomePageState, responsável por armazenar variáveis e lógicas de interação da tela
4. _MyHomePageState
Classe de lógica de estado, responsável por processar lógica, renderizar e atualizar a página
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Code language: JavaScript (javascript)
int _counter = 0: Dado variável da página: valor do contador_incrementCounter(): Evento ao clicar no botãosetState()avisa ao Flutter que os dados mudaram e a interface deve ser redesenhada- Incrementa o contador em +1
build(): Executado toda vez que houver atualização, retorna todo o layout da página
5. Scaffold: Modelo de página
Modelo de layout de página, pertence à classe _MyHomePageState
appBar: Barra de título superiorbody: Conteúdo principal da páginaCentercentraliza os elementos,Columnorganiza os textos verticalmente
floatingActionButton: Botão circular de mais no canto inferior direito, vinculado ao método de incremento no clique
Fluxo completo de execução
- Início do programa → executa
main→ carregaMyApp MyApprenderizaMaterialApp→ carrega a página inicialMyHomePage- A página renderiza barra de título, textos centralizados e botão de soma
- Clique no botão → executa
_incrementCounter+setStateredesenha a tela → número atualizado
Entendendo nosso primeiro projeto Flutter