This episode covers Flutter and cross-platform development: Flutter's architecture with Dart integration, building a simple Flutter app, the widget tree and state management with hot reload, and sharing Dart code between Flutter and the server.

Flutter is the main reason many people learn Dart. With a single codebase, Flutter produces native applications for Android, iOS, web, and desktop — and the language it uses is Dart. Episode 12 dissects Flutter's architecture, how to build an application, and how Dart connects all the layers.
You'll understand how the Flutter engine works, build a widget tree, use state management, leverage hot reload, and share Dart business logic with the server.
By the end of the episode, you'll see why the Dart and Flutter combination is an efficient answer to multiplatform development.
Flutter consists of several layers:
Your Dart code is compiled AOT into machine code at release time, so Flutter applications perform at native level.
Even though the UI lives in Flutter, applications still need platform channels for native features like camera and sensors:
import 'package:flutter/services.dart';
Future<String> ambilVersi() async {
const channel = MethodChannel('com.example/versi');
return await channel.invokeMethod('getVersi');
}MethodChannel('com.example/versi') opens a communication path between Dart code and native code. Flutter plugins use this pattern widely.
Create a project and see your first application:
flutter create belajar_flutter
cd belajar_flutter
flutter runflutter create belajar_flutter generates a project with the lib/main.dart file. Run flutter run to choose a device — emulator, browser, or physical device — and the app appears immediately.
Replace the contents of lib/main.dart with a simple widget:
import 'package:flutter/material.dart';
void main() => runApp(const AplikasiSaya());
class AplikasiSaya extends StatelessWidget {
const AplikasiSaya({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Belajar Flutter')),
body: const Center(child: Text('Halo, Dart!')),
),
);
}
}MaterialApp and Scaffold provide the standard Material page structure. Center(child: Text('Halo, Dart!')) displays text in the center of the screen.
All Flutter UI is a tree of widgets. Stateless widgets don't change, while stateful widgets hold state that can change during user interaction. This structure makes the UI declarative: the UI is a function of state.
The main strength of Flutter development is hot reload: change code, save, and the changes appear within seconds without losing application state. flutter run in debug mode supports this by default, and hot restart restarts from scratch if the structural changes go deeper.
For simple state, use setState:
import 'package:flutter/material.dart';
class Penghitung extends StatefulWidget {
@override
State<Penghitung> createState() => _PenghitungState();
}
class _PenghitungState extends State<Penghitung> {
int _angka = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text('$_angka'),
ElevatedButton(
onPressed: () => setState(() => _angka++),
child: const Text('Tambah'),
),
],
),
),
);
}
}setState(() => _angka++) tells Flutter that state changed so the widget gets rebuilt. For large applications, state management switches to provider or Riverpod (episode 18).
One of Dart's hidden advantages: business logic can be used in Flutter and the server at the same time. Separate the logic into a pure Dart package without Flutter dependencies:
dart create -t package domain_core
cd domain_coredart create -t package domain_core creates a pure library package. This package can then be added as a dependency of both the Flutter app (flutter pub add) and a server application (dart pub add) — validation, price calculations, and business rules are written once and used everywhere.
Key takeaways:
flutter create generates a project; flutter run runs the app on a device.setState is enough for simple state; larger frameworks for scale.In the next episode 13, we'll cover security and data handling — safe input validation, encryption and secure storage, secrets handling, network calls with HTTPS and certificates, and secure coding practices in Dart.