Menguasai cross-platform dengan Flutter: filosofi widget tree yang membangun seluruh UI dengan kode, renderer Impeller yang menggantikan Skia, bahasa Dart, serta praktik membangun halaman Fitku dengan performa tinggi dari satu codebase

Setelah melihat React Native di episode 5, kini kita hadapi pesaing utamanya: Flutter. Kalau RN memetakan komponen ke native view, Flutter mengambil jalan berbeda — ia menggambar seluruh UI sendiri memakai widget tree dan renderer kustom. Hasilnya: konsistensi visual yang sempurna di semua platform, dan performa yang mendekati native.
Mengapa Flutter populer? Karena pendekatan "semua adalah widget" sangat konsisten dan tooling-nya (hot reload) sangat nyaman. Banyak tim yang menginginkan UI pixel-perfect di dua platform memilih Flutter.
Flutter memakai Dart — bahasa yang dikompilasi ahead-of-time (AOT) untuk performa rilis dan just-in-time (JIT) untuk hot reload saat development. Sintaksnya mudah dipelajari bagi yang sudah kenal Java/C#/TypeScript:
class Workout {
final String name;
final int durationMinutes;
Workout(this.name, this.durationMinutes);
int get caloriesBurned => durationMinutes * 7;
}
void main() {
final run = Workout("Lari pagi", 30);
print("Bakar ${run.caloriesBurned} kalori");
}Dart memakai null safety sejak 3.0: semua tipe secara default non-nullable. Ini mencegah kelas error null reference yang menghantui bahasa lain.
Di Flutter, semua adalah widget — layar, teks, layout, bahkan spacing. UI dibangun sebagai pohon widget (widget tree):
import 'package:flutter/material.dart';
void main() => runApp(const FitkuApp());
class FitkuApp extends StatelessWidget {
const FitkuApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const HomeScreen(),
);
}
}Ada dua jenis widget: StatelessWidget (statis) dan StatefulWidget (menyimpan state dengan setState). Kalian juga memakai StatelessWidget untuk komponen kecil yang reusable:
class StepCounter extends StatefulWidget {
const StepCounter({super.key});
@override
State<StepCounter> createState() => _StepCounterState();
}
class _StepCounterState extends State<StepCounter> {
int _steps = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Langkah: $_steps', style: Theme.of(context).textTheme.titleLarge),
FilledButton(
onPressed: () => setState(() => _steps++),
child: const Text('Tambah langkah'),
),
],
);
}
}setState memberi tahu framework bahwa state berubah → widget di-rebuild. Ini pola deklaratif yang sama dengan Compose/SwiftUI.
Flutter lama men-render memakai Skia; sejak Flutter 3.10+ di iOS dan selanjutnya di Android, renderer baru Impeller menggantikannya:
Hasilnya: scrolling 60/120fps yang halus bahkan di hardware kelas menengah.
import 'package:flutter/material.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _steps = 0;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('Halo, Fitku!', style: theme.textTheme.headlineMedium),
const SizedBox(height: 16),
Card(
color: theme.colorScheme.primaryContainer,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Langkah hari ini',
style: theme.textTheme.labelLarge),
Text('$_steps', style: theme.textTheme.displayMedium),
],
),
),
),
const SizedBox(height: 16),
FilledButton(
onPressed: () => setState(() => _steps++),
child: const Text('Tambah langkah'),
),
],
),
),
),
);
}
}Perhatikan penggunaan SafeArea (menghindari notches) dan Card material — Flutter membawa Material Design secara bawaan, dan kalian bisa beralih ke desain kustom kapan pun.
Tip
Mulai proyek Flutter dengan flutter create fitku lalu jalankan dengan flutter run. Untuk state management skala besar, ekosistem Flutter menawarkan Provider, Riverpod, dan Bloc — kita bandingkan semuanya di episode 9.
setState untuk state global: buntu saat fitur kompleks — segera pindah ke Riverpod/Bloc (episode 9).const constructor: banyak rebuild tidak perlu. Selalu tandai widget dengan const bila memungkinkan.MediaQuery berlebihan: baca ukuran layar sekali di layout utama, bukan di tiap widget.Note
Kalian ingin memperdalam Dart atau Flutter? Series learn-dart-series dan learn-flutter-series di repo ini menyediakan kurikulum khusus. Episode ini memberi konteks cross-platform; series tersebut mendalaminya lebih jauh.
Pada episode 6 ini, kalian telah menguasai fondasi Flutter:
Di episode 7 selanjutnya kita bahas tren yang naik 2x lipat di 2026: Kotlin Multiplatform & Compose Multiplatform — berbagi business logic antar platform lewat KMP, dan berbagi UI lewat Compose Multiplatform. Sampai jumpa!