The edit-reload loop is Flutter's superpower, and knowing the project layout saves hours of confusion.
Install the Flutter SDK (it bundles Dart), then check your setup with flutter doctor, which reports missing Android, Xcode or browser toolchains.
flutter create my_app generates a project:
lib/main.dart— your Dart code;main()callsrunApp(MyApp()).pubspec.yaml— dependencies, assets and fonts.android/,ios/,web/,macos/... — thin native host projects you rarely touch.test/— tests.
flutter run builds and launches on a connected device, emulator, simulator or Chrome (-d chrome); flutter devices lists targets. IDE plug-ins for VS Code and Android Studio do the same with a debugger.
In debug mode the app runs on the Dart VM with a JIT, which enables:
- Hot reload (
rin the terminal, or save in the IDE): injects changed code and rebuilds the widget tree while keeping state. Takes under a second. - Hot restart (
R): restarts the app and resets state; needed after changingmain(), global initializers, enum declarations or a class from stateless to stateful.
Debug builds are slow and large on purpose. Measure performance only with flutter run --profile, and ship with flutter build apk, appbundle, ipa or web, which compile AOT.
flutter pub add <package> adds dependencies from pub.dev, just like dart pub.
Example
// lib/main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(child: Text('Hello, Flutter!')), // edit + save = hot reload
),
);
}
}
// Terminal:
// flutter doctor # check toolchains
// flutter run -d chrome # r = hot reload, R = hot restart, q = quitRemember
main()callsrunAppwith your root widget- Hot reload keeps state; hot restart resets it
- Judge performance only in profile or release builds
Watch out for
- Expecting hot reload to pick up changes to
main()or static initializers — use hot restart.