Answer
Overview
Flutter apps are not converted to native apps in the traditional sense. Instead, Flutter compiles to native ARM/x86 machine code that runs directly on the device. The Flutter framework itself handles rendering through its own engine.
How Flutter Apps Work
Architecture Layers
text┌─────────────────────────────────┐ │ Flutter Framework │ ← Dart code (widgets, logic) │ (Dart) │ ├─────────────────────────────────┤ │ Flutter Engine │ ← Skia graphics, Dart runtime │ (C++, Skia, Dart VM) │ ├─────────────────────────────────┤ │ Platform Embedder │ ← Android/iOS native wrapper │ (Android SDK / iOS UIKit) │ ├─────────────────────────────────┤ │ Operating System (Android/iOS)│ ← Native platform └─────────────────────────────────┘
Compilation Process
Debug Mode (Development)
textDart Source Code ↓ JIT Compilation (Just-In-Time) ↓ Dart VM executes bytecode ↓ Hot Reload enabled (fast iteration)
Characteristics:
- Code compiled on-the-fly
- Slower performance
- Enables hot reload
Release Mode (Production)
textDart Source Code ↓ AOT Compilation (Ahead-Of-Time) ↓ Native ARM/x86 machine code ↓ Runs directly on device (no interpreter)
Characteristics:
- Compiled to native machine code
- Maximum performance (near-native)
- No hot reload
Platform-Specific Build Process
Android
bashflutter build apk --release
What happens:
text1. Dart code → AOT compiled to ARM/x86 machine code 2. Flutter engine (C++ libraries) → bundled 3. Android wrapper (MainActivity.java/.kt) → created 4. Resources (assets, images) → packaged 5. All combined into APK/App Bundle
Output structure:
textapp-release.apk ├── lib/ │ ├── arm64-v8a/ # ARM 64-bit native code │ ├── armeabi-v7a/ # ARM 32-bit native code │ └── x86_64/ # x86 64-bit (emulators) ├── assets/ │ └── flutter_assets/ # Images, fonts, etc. ├── META-INF/ └── AndroidManifest.xml
iOS
bashflutter build ios --release
What happens:
text1. Dart code → AOT compiled to ARM machine code 2. Flutter engine → embedded as framework 3. iOS wrapper (AppDelegate.swift) → created 4. Compiled into .app bundle 5. Signed and packaged as .ipa
Output structure:
textRunner.app ├── Frameworks/ │ ├── Flutter.framework # Flutter engine │ └── App.framework # Compiled Dart code ├── Assets.car # Asset catalog └── Info.plist
Key Components in Built App
1. Flutter Engine (C++)
What it includes:
- Skia graphics library (rendering)
- Dart runtime (VM)
- Text rendering
- Platform channels
Size: ~4-5 MB
textAndroid: libflutter.so iOS: Flutter.framework
2. Compiled Dart Code
Your app's business logic and UI code compiled to native machine code.
dart// Your Dart code void main() { runApp(MyApp()); } // Compiled to → // Native ARM assembly code (machine code)
3. Platform Embedder
Minimal native wrapper that hosts the Flutter engine.
Android:
kotlin// MainActivity.kt import io.flutter.embedding.android.FlutterActivity class MainActivity: FlutterActivity() { // Flutter engine runs here }
iOS:
swift// AppDelegate.swift import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { // Flutter engine runs here }
How Rendering Works
Traditional Native Apps
textDart/Java/Swift Code ↓ Platform Widgets (UIButton, TextView) ↓ Platform Rendering (iOS UIKit, Android Canvas) ↓ GPU
Flutter Apps
textDart Code (Widgets) ↓ Flutter Framework (builds widget tree) ↓ Skia Engine (renders to canvas) ↓ GPU (direct rendering)
Key difference: Flutter bypasses platform widgets and renders everything itself using Skia.
Platform Channels (Native Integration)
Flutter can call native code when needed:
dart// Dart side import 'package:flutter/services.dart'; static const platform = MethodChannel('com.example/battery'); Future<int> getBatteryLevel() async { final int result = await platform.invokeMethod('getBatteryLevel'); return result; }
kotlin// Android side (Kotlin) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL) .setMethodCallHandler { call, result -> if (call.method == "getBatteryLevel") { val batteryLevel = getBatteryLevel() result.success(batteryLevel) } }
Flow:
textFlutter (Dart) ↓ Platform Channel Native Code (Kotlin/Swift) ↓ Platform APIs (Battery, Camera, etc.) ↓ Response Flutter (Dart)
Build Size Breakdown
Minimal Flutter App (Release)
textAndroid APK: ├── Flutter engine: 4-5 MB ├── Compiled Dart code: 1-2 MB ├── Assets/fonts: 1-3 MB ├── Android wrapper: 0.5 MB └── Total: ~7-10 MB iOS IPA: ├── Flutter.framework: 4-5 MB ├── App.framework: 1-2 MB ├── Assets: 1-3 MB ├── iOS wrapper: 0.5 MB └── Total: ~7-10 MB
Why Flutter is Fast
1. AOT Compilation
textNative app: Source → Native code Flutter app: Dart → AOT → Native ARM code (same as native!)
No interpretation at runtime = maximum performance.
2. Direct GPU Rendering
textFlutter → Skia → GPU (No platform widget overhead)
3. Efficient Widget Tree
dart// Only rebuilds what changed setState(() { _counter++; // Only this widget rebuilds });
Debugging the Build
View APK contents (Android)
bash# Extract APK unzip app-release.apk -d extracted # View native libraries ls extracted/lib/arm64-v8a/ # Output: libflutter.so, libapp.so
View IPA contents (iOS)
bash# Extract IPA unzip Runner.ipa -d extracted # View frameworks ls extracted/Payload/Runner.app/Frameworks/ # Output: Flutter.framework, App.framework
Comparison with Other Frameworks
| Framework | Compilation | Rendering |
|---|---|---|
| Native | Native code | Platform widgets |
| Flutter | AOT → Native code | Skia engine (custom) |
| React Native | JavaScript (interpreted) | Native widgets via bridge |
| Ionic | JavaScript (WebView) | HTML/CSS (slow) |
Key advantage: Flutter compiles to native code like native apps, but renders using its own engine.
Key Differences from React Native
| Aspect | Flutter | React Native |
|---|---|---|
| Language | Dart (compiled to native) | JavaScript (interpreted) |
| Bridge | No bridge (direct code) | JavaScript bridge (slow) |
| Rendering | Skia engine | Native widgets |
| Performance | Near-native (95-98%) | Good (70-80%) |
Why faster: No JavaScript bridge, direct native code.
Platform-Specific Features
Flutter can access platform features via:
1. Platform Channels (Custom)
dart// Call native iOS/Android code final result = await platform.invokeMethod('nativeMethod');
2. Plugins (Pre-built)
yamldependencies: camera: ^0.10.0 # Camera access location: ^4.4.0 # GPS firebase_core: ^2.4.0 # Firebase
Plugins use platform channels internally.
Build Commands
Android
bash# Debug (JIT) flutter run # Release (AOT) flutter build apk --release # APK flutter build appbundle --release # App Bundle (Play Store) # Split per ABI (reduce size) flutter build apk --split-per-abi
iOS
bash# Debug flutter run # Release (AOT) flutter build ios --release flutter build ipa --release # For App Store
Key Takeaways
Not converted: Flutter doesn't convert to native code—it compiles directly to native ARM/x86 machine code.
Rendering: Flutter uses its own Skia engine, not platform widgets.
Performance: Near-native (95-98%) because it's real compiled native code.
Platform integration: Access native features via platform channels.