En la lección anterior creamos nuestro primer proyecto Flutter, es un proyecto muy simple que solo contiene un botón que incrementa un número al pulsarlo. A continuación se muestra la estructura de carpetas de este proyecto.
Estructura de carpetas del proyecto

Verás muchas carpetas y archivos como android, web, windows, lib, test, etc. ¿Dónde está el código fuente que debes escribir? ¿En android? ¿En windows? En realidad no, está en la carpeta lib. Al abrir lib verás un archivo main.dart.

La carpeta lib almacenará todo tu código fuente en adelante. Escribirás código en Dart, no en Java ni C++. Flutter utiliza el lenguaje Dart. ¿Por qué existen entonces las carpetas android, web, windows y demás?
Es fácil de entender: Flutter puede compilarse en aplicaciones multiplataforma gracias a estas carpetas.
Flutter es un framework de un único código Dart para ejecución en múltiples plataformas. La carpeta lib contiene el código de negocio común multiplataforma que escribes; mientras que las carpetas android / windows / web / macos / linux son proyectos nativos de cada plataforma anfitriona, encargados de integrar Flutter en el sistema correspondiente para su ejecución.
1. Carpeta android
Se trata del proyecto nativo de la plataforma Android
Proporciona el contenedor de ejecución de la app Android y aloja el motor de renderizado de Flutter. Aquí se configuran todos los ajustes de bajo nivel relacionados con Android: permisos de la app, iconos, nombre de paquete, etc. Es decir, aquí puedes configurar elementos exclusivos de Android y llamar a APIs nativas del sistema (cámara, bluetooth, notificaciones, ubicación, etc.)
2. Carpeta windows
Corresponde al proyecto nativo de escritorio Windows
Es un proyecto nativo C++ Win32 que crea ventanas del sistema Windows e inicializa el motor de renderizado Skia. Skia es la librería gráfica de Google, utilizada por Flutter para renderizar ventanas y controles en aplicaciones de escritorio.
Los archivos dentro de la carpeta windows gestionan la configuración de bajo nivel del software de escritorio Windows: tamaño de ventana, barra de título, iconos, bandeja del sistema (el icono en la esquina inferior derecha de Windows).
Finalmente puedes empaquetar el proyecto en formatos exe o msix para publicarlo en Microsoft Store, entre otros.
3. Carpeta web
Proyecto de página web estática (HTML/JS/CSS) que proporciona el punto de entrada web index.html. Tu código Dart se compilará finalmente en recursos web.
Permite configurar el título de la página, iconos, recursos estáticos y rutas. Al compilar genera archivos HTML/CSS/JS listos para desplegar en un servidor y abrir en cualquier navegador.
Otros directorios
No usamos iOS, macOS ni Linux en este ejemplo porque no marcamos esas opciones al crear el proyecto, por lo que esas carpetas no aparecen aquí. Sin embargo, su funcionamiento es idéntico.
ios: Proyecto nativo Xcode de Apple iOS, para empaquetar archivos ipa y publicar en iPhone
macos: Proyecto nativo Cocoa para escritorio macOS, cliente para ordenadores Mac
linux: Proyecto de escritorio Linux basado en GTK
En la esquina superior derecha de Android Studio puedes seleccionar distintas plataformas para compilar versiones diferentes de la aplicación. También puedes usar la línea de comandos directamente; de hecho, al elegir una plataforma y pulsar el triángulo verde en Android Studio, se ejecutan internamente comandos de Flutter.
# Ejecutar versión Android, lee configuraciones de la carpeta android
flutter run -d android
# Ejecutar escritorio Windows, lee el proyecto C++ de la carpeta windows
flutter run -d windows
# Ejecutar versión web, lee el archivo html de la carpeta web
flutter run -d chromeLenguaje del código: PHP (php)

Abre el archivo runner / main.cpp dentro de la carpeta 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;
}
Lenguaje del código: PHP (php)
Si compilas para Windows Desktop, este main.cpp es el punto de entrada real del programa: se ejecuta primero este archivo C++ y luego pasa a tu lib/main.dart.
Del mismo modo, al abrir la carpeta android verás una estructura casi idéntica a los proyectos Android desarrollados con Kotlin o Java.

También contiene la carpeta src, el archivo AndroidManifest.xml, MainActivity y otros elementos que te resultarán familiares si has desarrollado apps Android. En efecto, al crear una app Android con Flutter, la ejecución comienza desde esta carpeta android.
Igualmente, al abrir la carpeta web encontrarás el punto de entrada web index.html

Archivos Dart
El archivo main.dart dentro de lib será el lugar donde realizarás la mayor parte del desarrollo. Puedes crear subcarpetas y añadir otros archivos Dart dentro de lib.
Abre main.dart
// Importar librería de componentes Material
import 'package:flutter/material.dart';
// Función de entrada del programa
void main() {
runApp(const MyApp());
}
// Componente raíz de la aplicación (sin estado)
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
// Configuración global del tema
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
// Página principal
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
// Página principal (componente con estado)
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
// Parámetro de título de la página
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
// Clase de gestión de estado de la página principal
class _MyHomePageState extends State<MyHomePage> {
// Variable contador
int _counter = 0;
// Método para incrementar el contador
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
// Plantilla base de layout de página
return Scaffold(
// Barra de navegación superior
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
// Contenido principal de la página
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter', // Muestra la variable numérica anterior
style: Theme.of(context).textTheme.headlineMedium, // Estilo de texto
),
],
),
),
// Botón flotante inferior derecho: onPressed ejecuta _incrementCounter, tooltip es el texto de ayuda, child configura el icono
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Lenguaje del código: JavaScript (javascript)
1. Sección de entrada
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
Lenguaje del código: JavaScript (javascript)
- Importa Material, el conjunto oficial de componentes UI de Google (botones, páginas, textos, etc.). Apple cuenta con su propio framework de interfaz.
maines el único punto de entrada de un programa Dart;runApp()inicia la aplicación y monta el componente raízMyApp
2. MyApp: Componente raíz global
Se trata de un StatelessWidget (componente sin estado), lo explicaremos más adelante, por ahora basta con saberlo.
class MyApp extends StatelessWidget {
const MyApp({super.key});
// Componente raíz de tu aplicación
@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'),
);
}
}
Lenguaje del código: JavaScript (javascript)
- Configuración global: Nombre de la app, tema general, página inicial
MaterialApp: Contenedor de aplicaciones con estilo Material, gestiona rutas, temas y títulos de forma unificadahomedefine la página predeterminada al abrir la app:MyHomePage
3. MyHomePage: Página principal
Página que se muestra por defecto al abrir la ventana o la app, es un StatefulWidget (componente con estado), lo veremos con detalle después.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}Lenguaje del código: JavaScript (javascript)
- Al contener datos variables (el número del contador), se usa un componente con estado
- Recibe el parámetro
titledesde fuera y se lee mediantewidget.titleen la clase de estado - Debe ir acompañado de una clase
_MyHomePageStatededicada a almacenar variables y lógica de interacción de la página
4. _MyHomePageState
Clase de lógica de estado, encargada de gestionar la lógica, renderizado y actualizaciones de la 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),
),
);
}
}Lenguaje del código: JavaScript (javascript)
int _counter = 0: Dato variable de la página: valor del contador_incrementCounter(): Evento al pulsar el botónsetState()avisa a Flutter que los datos han cambiado y debe refrescar la interfaz de usuario- Incrementa el contador en 1
build(): Se ejecuta en cada refresco y devuelve el layout completo de la página
5. Scaffold: Plantilla de página
Plantilla de layout de página, pertenece a la clase _MyHomePageState
appBar: Barra de título superiorbody: Contenido principal de la páginaCentercentra los elementos,Columnorganiza los textos en vertical
floatingActionButton: Botón circular con signo más en la esquina inferior derecha, vinculado al método de incremento al pulsar
Flujo general de ejecución
- Inicio del programa → ejecución de
main→ carga deMyApp MyApprenderizaMaterialApp→ carga la página inicialMyHomePage- La página renderiza la barra de título, los textos centrados y el botón de suma
- Al pulsar el botón → se ejecuta
_incrementCounter+setStateredibuja la página → el número se actualiza
Comprender nuestro primer proyecto Flutter