├── .gitignore ├── README.md ├── builds ├── flutter-release.aab ├── flutter-release.apk ├── kmp-release.aab ├── kmp-release.apk ├── native-release.aab └── native-release.apk ├── docs └── images │ ├── chart_app_size.png │ └── chart_startup_times.png ├── flutter └── app │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── analysis_options.yaml │ ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── app │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── values-night │ │ │ │ └── styles.xml │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── macrobenchmark │ │ ├── .gitignore │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── macrobenchmark │ │ │ └── ExampleStartupBenchmark.kt │ └── settings.gradle │ ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ ├── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ │ └── LaunchImage.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ └── README.md │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h │ └── RunnerTests │ │ └── RunnerTests.swift │ ├── lib │ └── main.dart │ ├── pubspec.lock │ ├── pubspec.yaml │ └── test │ └── widget_test.dart ├── kmp └── cats │ ├── .gitignore │ ├── app │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── cats │ │ │ └── MainActivity.kt │ │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.webp │ │ └── ic_launcher_round.webp │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── themes.xml │ │ └── xml │ │ ├── backup_rules.xml │ │ └── data_extraction_rules.xml │ ├── build.gradle.kts │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── iosCats │ ├── iosCats.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ ├── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcuserdata │ │ │ │ └── jacob.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcuserdata │ │ │ └── jacob.xcuserdatad │ │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── iosCats │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ │ ├── ContentView.swift │ │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ │ └── iosCatsApp.swift │ ├── macrobenchmark │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── example │ │ └── macrobenchmark │ │ └── ExampleStartupBenchmark.kt │ ├── settings.gradle.kts │ └── shared │ ├── build.gradle.kts │ └── src │ ├── androidMain │ └── kotlin │ │ └── com │ │ └── sample │ │ └── cats │ │ └── network │ │ └── createKtorEngine.kt │ ├── commonMain │ └── kotlin │ │ └── com │ │ └── sample │ │ └── cats │ │ ├── data │ │ ├── CatImageDto.kt │ │ └── DefaultCatImagesRepository.kt │ │ ├── domain │ │ ├── CatImage.kt │ │ └── CatImagesRepository.kt │ │ ├── network │ │ └── createKtorEngine.kt │ │ └── ui │ │ ├── CatImagesScreen.kt │ │ ├── CatsApp.kt │ │ └── theme │ │ ├── CatImagesViewModel.kt │ │ ├── Color.kt │ │ ├── Theme.kt │ │ └── Type.kt │ └── iosMain │ └── kotlin │ ├── com │ └── sample │ │ └── cats │ │ └── network │ │ └── createKtorEngine.kt │ └── main.ios.kt ├── native-android └── cats │ ├── .gitignore │ ├── app │ ├── .gitignore │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── cats │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── cats │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── data │ │ │ │ ├── CatImageDto.kt │ │ │ │ └── DefaultCatImagesRepository.kt │ │ │ │ ├── domain │ │ │ │ ├── CatImage.kt │ │ │ │ └── CatImagesRepository.kt │ │ │ │ └── ui │ │ │ │ ├── CatImagesScreen.kt │ │ │ │ ├── CatsApp.kt │ │ │ │ └── theme │ │ │ │ ├── CatImagesViewModel.kt │ │ │ │ ├── Color.kt │ │ │ │ ├── Theme.kt │ │ │ │ └── Type.kt │ │ └── res │ │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── drawable │ │ │ └── ic_launcher_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── themes.xml │ │ │ └── xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── example │ │ └── cats │ │ └── ExampleUnitTest.kt │ ├── build.gradle.kts │ ├── gradle.properties │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── macrobenchmark │ ├── .gitignore │ ├── build.gradle.kts │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── example │ │ └── macrobenchmark │ │ └── ExampleStartupBenchmark.kt │ └── settings.gradle.kts └── native-ios └── Cats ├── Cats.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ │ └── Package.resolved │ └── xcuserdata │ │ └── jacob.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── jacob.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── Cats ├── Assets.xcassets ├── AccentColor.colorset │ └── Contents.json ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── CatImage.swift ├── CatImagesViewModel.swift ├── CatsApp.swift ├── ContentView.swift └── Preview Content └── Preview Assets.xcassets └── Contents.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea 5 | .DS_Store 6 | /build 7 | */build 8 | /captures 9 | .externalNativeBuild 10 | .cxx 11 | local.properties -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter versus Native versus KMP: a Performance Comparison 2 | 3 | Comparing the performance of the same app in Flutter, native and Kotlin Multiplatform (KMP) on Android and iOS. 4 | 5 | ## 🐈 Sample app 6 | 7 | The app will contain a single screen, load cat pictures from a public API and show them in a horizontal list. 8 | Each picture can be clicked to show it zoomed in below the list. 9 | 10 | ## 📂 Technology overview 11 | 12 | | Folder | Technology | UI Framework | Network lib | Image lib | 13 | |-------------------|------------------------|--------------------------|-----------------------------------------------------|---------------------------------------------------------------| 14 | | `/flutter` | Cross-platform, Dart | Flutter | [http.dart](https://pub.dev/packages/http) | Built-in image widget | 15 | | `/kmp` | Cross-platform, Kotlin | Compose UI Multiplatform | [Ktor](https://github.com/ktorio/ktor) | [Kamel](https://github.com/Kamel-Media/Kamel) | 16 | | `/native-ios` | Native, Swift | SwiftUI | [Alamofire](https://github.com/Alamofire/Alamofire) | [AlamofireImage](https://github.com/Alamofire/AlamofireImage) | 17 | | `/native-android` | Native, Kotlin | Compose UI | [Ktor](https://github.com/ktorio/ktor) | [Kamel](https://github.com/Kamel-Media/Kamel) | 18 | 19 | ### 📦 Builds 20 | 21 | Release builds are available in `/builds`. 22 | 23 | ## 📊 Benchmark results 24 | 25 | ### 📦 App size 26 | 27 | Android sizes were measured by running Bundletool* on the signed, minified release bundles to create an APK set for a 28 | Pixel 4a, and then running `get-size` on that APK set. iOS sizes were measured running the App Thinning Size report. 29 | 30 | | Technology | Android | iOS | Remarks | 31 | |------------------------------|----------|----------------------------------|--------------------------------------------------------------| 32 | | **Native** (Compose/SwiftUI) | 1.463 MB | 1.7 MB | | 33 | | **KMP** (Compose) | 1.463 MB | 24.8 MB (v1.4)
32.2 MB (v1.5) | Includes Skia on iOS, where Android relies on built-in Skia. | 34 | | **Flutter** | 6.828 MB | 17.9 MB | Also includes Skia on iOS + Flutter framework. | 35 | 36 | Note: due to https://github.com/Kamel-Media/Kamel/issues/47 the Kamel library isn't being minified. Once that's fixed, 37 | the Android native and Android KMP builds will both be smaller. 38 | 39 | *commands used: 40 | 41 | * `bundletool build-apks --connected-device --bundle=release.aab --output=release.apks` 42 | * `bundletool get-size total --apks=release.apks` 43 | 44 | ### 🚀 Startup 45 | 46 | #### Android 47 | 48 | Android startup benchmarks were executed 49 | using [Macrobenchmark](https://developer.android.com/topic/performance/benchmarking/macrobenchmark-overview), 5 times on 50 | a Pixel 4a. Test suite was run twice 51 | in alternating order. 52 | 53 | | App | min. | median | max. | 54 | |---------------------|----------|----------|----------| 55 | | **Native** Android | 408.7 ms | 413.1 ms | 423.1 ms | 56 | | **KMP** Android | 403.6 ms | 425.3 ms | 466.4 ms | 57 | | **Flutter** Android | 600.5 ms | 634.2 ms | 649.8 ms | 58 | 59 | #### iOS 60 | 61 | The iOS startup tests were run on an iPhone 12 Mini. 62 | 63 | | App | Duration (AppLaunch) | 64 | |-----------------|----------------------| 65 | | **Native** iOS | 1.441 s | 66 | | **KMP** iOS | 1.618 s | 67 | | **Flutter** iOS | 1.608 s | -------------------------------------------------------------------------------- /builds/flutter-release.aab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/flutter-release.aab -------------------------------------------------------------------------------- /builds/flutter-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/flutter-release.apk -------------------------------------------------------------------------------- /builds/kmp-release.aab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/kmp-release.aab -------------------------------------------------------------------------------- /builds/kmp-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/kmp-release.apk -------------------------------------------------------------------------------- /builds/native-release.aab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/native-release.aab -------------------------------------------------------------------------------- /builds/native-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/builds/native-release.apk -------------------------------------------------------------------------------- /docs/images/chart_app_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/docs/images/chart_app_size.png -------------------------------------------------------------------------------- /docs/images/chart_startup_times.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/docs/images/chart_startup_times.png -------------------------------------------------------------------------------- /flutter/app/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Symbolication related 36 | app.*.symbols 37 | 38 | # Obfuscation related 39 | app.*.map.json 40 | 41 | # Android Studio will place build artifacts here 42 | /android/app/debug 43 | /android/app/profile 44 | /android/app/release 45 | -------------------------------------------------------------------------------- /flutter/app/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 17 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 18 | - platform: android 19 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 20 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 21 | - platform: ios 22 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 23 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 24 | 25 | # User provided section 26 | 27 | # List of Local paths (relative to this file) that should be 28 | # ignored by the migrate tool. 29 | # 30 | # Files that are not part of the templates will be ignored by default. 31 | unmanaged_files: 32 | - 'lib/main.dart' 33 | - 'ios/Runner.xcodeproj/project.pbxproj' 34 | -------------------------------------------------------------------------------- /flutter/app/README.md: -------------------------------------------------------------------------------- 1 | # app 2 | 3 | Cats. -------------------------------------------------------------------------------- /flutter/app/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /flutter/app/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /flutter/app/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | namespace "com.example.app" 30 | compileSdkVersion flutter.compileSdkVersion 31 | ndkVersion flutter.ndkVersion 32 | 33 | compileOptions { 34 | sourceCompatibility JavaVersion.VERSION_1_8 35 | targetCompatibility JavaVersion.VERSION_1_8 36 | } 37 | 38 | kotlinOptions { 39 | jvmTarget = '1.8' 40 | } 41 | 42 | sourceSets { 43 | main.java.srcDirs += 'src/main/kotlin' 44 | } 45 | 46 | defaultConfig { 47 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 48 | applicationId "com.example.app" 49 | // You can update the following values to match your application needs. 50 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 51 | minSdkVersion flutter.minSdkVersion 52 | targetSdkVersion flutter.targetSdkVersion 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | 57 | buildTypes { 58 | release { 59 | minifyEnabled true 60 | shrinkResources true 61 | // TODO: Add your own signing config for the release build. 62 | // Signing with the debug keys for now, so `flutter run --release` works. 63 | signingConfig signingConfigs.debug 64 | } 65 | benchmark { 66 | initWith(buildTypes.getByName("release")) 67 | matchingFallbacks += ["release"] 68 | debuggable false 69 | } 70 | } 71 | } 72 | 73 | flutter { 74 | source '../..' 75 | } 76 | 77 | dependencies { 78 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 79 | } 80 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/kotlin/com/example/app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.app 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /flutter/app/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter/app/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.3.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | tasks.register("clean", Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /flutter/app/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /flutter/app/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 6 | -------------------------------------------------------------------------------- /flutter/app/android/macrobenchmark/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /flutter/app/android/macrobenchmark/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.test") 3 | id("org.jetbrains.kotlin.android") 4 | } 5 | 6 | android { 7 | namespace = "com.example.macrobenchmark" 8 | compileSdk = 33 9 | 10 | compileOptions { 11 | sourceCompatibility = JavaVersion.VERSION_1_8 12 | targetCompatibility = JavaVersion.VERSION_1_8 13 | } 14 | 15 | kotlinOptions { 16 | jvmTarget = "1.8" 17 | } 18 | 19 | defaultConfig { 20 | minSdk = 23 21 | targetSdk = 33 22 | 23 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 24 | } 25 | 26 | buildTypes { 27 | // This benchmark buildType is used for benchmarking, and should function like your 28 | // release build (for example, with minification on). It"s signed with a debug key 29 | // for easy local/CI testing. 30 | create("benchmark") { 31 | isDebuggable = true 32 | signingConfig = getByName("debug").signingConfig 33 | matchingFallbacks += listOf("release") 34 | } 35 | } 36 | 37 | targetProjectPath = ":app" 38 | experimentalProperties["android.experimental.self-instrumenting"] = true 39 | } 40 | 41 | dependencies { 42 | implementation("androidx.test.ext:junit:1.1.5") 43 | implementation("androidx.test.espresso:espresso-core:3.5.1") 44 | implementation("androidx.test.uiautomator:uiautomator:2.2.0") 45 | implementation("androidx.benchmark:benchmark-macro-junit4:1.1.1") 46 | } 47 | 48 | androidComponents { 49 | beforeVariants(selector().all()) { 50 | it.enable = it.buildType == "benchmark" 51 | } 52 | } -------------------------------------------------------------------------------- /flutter/app/android/macrobenchmark/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /flutter/app/android/macrobenchmark/src/main/java/com/example/macrobenchmark/ExampleStartupBenchmark.kt: -------------------------------------------------------------------------------- 1 | package com.example.macrobenchmark 2 | 3 | import androidx.benchmark.macro.CompilationMode 4 | import androidx.benchmark.macro.StartupMode 5 | import androidx.benchmark.macro.StartupTimingMetric 6 | import androidx.benchmark.macro.junit4.MacrobenchmarkRule 7 | import androidx.test.ext.junit.runners.AndroidJUnit4 8 | import org.junit.Rule 9 | import org.junit.Test 10 | import org.junit.runner.RunWith 11 | 12 | /** 13 | * This is an example startup benchmark. 14 | * 15 | * It navigates to the device's home screen, and launches the default activity. 16 | * 17 | * Before running this benchmark: 18 | * 1) switch your app's active build variant in the Studio (affects Studio runs only) 19 | * 2) add `` to your app's manifest, within the `` tag 20 | * 21 | * Run this benchmark from Studio to see startup measurements, and captured system traces 22 | * for investigating your app's performance. 23 | */ 24 | @RunWith(AndroidJUnit4::class) 25 | class ExampleStartupBenchmark { 26 | @get:Rule 27 | val benchmarkRule = MacrobenchmarkRule() 28 | 29 | @Test 30 | fun startup() = benchmarkRule.measureRepeated( 31 | packageName = "com.example.app", 32 | metrics = listOf(StartupTimingMetric()), 33 | iterations = 5, 34 | startupMode = StartupMode.COLD 35 | ) { 36 | pressHome() 37 | startActivityAndWait() 38 | } 39 | } -------------------------------------------------------------------------------- /flutter/app/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | include ':macrobenchmark' 3 | 4 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 5 | def properties = new Properties() 6 | 7 | assert localPropertiesFile.exists() 8 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 9 | 10 | def flutterSdkPath = properties.getProperty("flutter.sdk") 11 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 12 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 13 | -------------------------------------------------------------------------------- /flutter/app/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /flutter/app/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter/app/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter/app/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | App 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | app 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /flutter/app/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /flutter/app/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /flutter/app/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:http/http.dart' as http; 5 | 6 | void main() { 7 | runApp(const MyApp()); 8 | } 9 | 10 | class CatImage { 11 | final String id; 12 | final String url; 13 | 14 | CatImage({required this.id, required this.url}); 15 | 16 | factory CatImage.fromJson(Map json) { 17 | return CatImage(id: json['id'], url: json['url']); 18 | } 19 | } 20 | 21 | class MyApp extends StatelessWidget { 22 | const MyApp({super.key}); 23 | 24 | // This widget is the root of your application. 25 | @override 26 | Widget build(BuildContext context) { 27 | return MaterialApp( 28 | title: 'Flutter Demo', 29 | theme: ThemeData( 30 | // This is the theme of your application. 31 | // 32 | // TRY THIS: Try running your application with "flutter run". You'll see 33 | // the application has a blue toolbar. Then, without quitting the app, 34 | // try changing the seedColor in the colorScheme below to Colors.green 35 | // and then invoke "hot reload" (save your changes or press the "hot 36 | // reload" button in a Flutter-supported IDE, or press "r" if you used 37 | // the command line to start the app). 38 | // 39 | // Notice that the counter didn't reset back to zero; the application 40 | // state is not lost during the reload. To reset the state, use hot 41 | // restart instead. 42 | // 43 | // This works for code too, not just values: Most code changes can be 44 | // tested with just a hot reload. 45 | colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), 46 | useMaterial3: true, 47 | ), 48 | home: const MyHomePage(title: 'Cats'), 49 | ); 50 | } 51 | } 52 | 53 | class MyHomePage extends StatefulWidget { 54 | const MyHomePage({super.key, required this.title}); 55 | 56 | // This widget is the home page of your application. It is stateful, meaning 57 | // that it has a State object (defined below) that contains fields that affect 58 | // how it looks. 59 | 60 | // This class is the configuration for the state. It holds the values (in this 61 | // case the title) provided by the parent (in this case the App widget) and 62 | // used by the build method of the State. Fields in a Widget subclass are 63 | // always marked "final". 64 | 65 | final String title; 66 | 67 | @override 68 | State createState() => _MyHomePageState(); 69 | } 70 | 71 | class _MyHomePageState extends State { 72 | List catImages = []; 73 | CatImage? selectedCatImage; 74 | 75 | @override 76 | void initState() { 77 | super.initState(); 78 | fetchCatImages(); 79 | } 80 | 81 | Future fetchCatImages() async { 82 | final response = await http 83 | .get(Uri.parse('https://api.thecatapi.com/v1/images/search?limit=10')); 84 | 85 | if (response.statusCode == 200) { 86 | List data = json.decode(response.body); 87 | List images = 88 | data.map((json) => CatImage.fromJson(json)).toList(); 89 | 90 | setState(() { 91 | catImages = images; 92 | }); 93 | } else { 94 | print('Failed to load images'); 95 | } 96 | } 97 | 98 | void setSelectedImage(CatImage image) { 99 | setState(() { 100 | selectedCatImage = image; 101 | }); 102 | } 103 | 104 | @override 105 | Widget build(BuildContext context) { 106 | // This method is rerun every time setState is called, for instance as done 107 | // by the _incrementCounter method above. 108 | // 109 | // The Flutter framework has been optimized to make rerunning build methods 110 | // fast, so that you can just rebuild anything that needs updating rather 111 | // than having to individually change instances of widgets. 112 | return Scaffold( 113 | appBar: AppBar( 114 | // TRY THIS: Try changing the color here to a specific color (to 115 | // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar 116 | // change color while the other colors stay the same. 117 | backgroundColor: Theme.of(context).colorScheme.inversePrimary, 118 | // Here we take the value from the MyHomePage object that was created by 119 | // the App.build method, and use it to set our appbar title. 120 | title: Text(widget.title), 121 | ), 122 | body: Center( 123 | child: Column( 124 | mainAxisAlignment: MainAxisAlignment.center, 125 | children: [ 126 | Container( 127 | height: 100, // Height of the horizontal list 128 | child: ListView.builder( 129 | scrollDirection: Axis.horizontal, 130 | itemCount: catImages.length, 131 | itemBuilder: (context, index) { 132 | return GestureDetector( 133 | onTap: () { 134 | setSelectedImage(catImages[index]); 135 | }, 136 | child: Padding( 137 | padding: const EdgeInsets.all(8.0), 138 | child: Image.network(catImages[index].url), 139 | ), 140 | ); 141 | }, 142 | ), 143 | ), 144 | Expanded( 145 | child: selectedCatImage != null 146 | ? Center( 147 | child: Image.network( 148 | selectedCatImage!.url, 149 | height: 300, 150 | ), 151 | ) 152 | : Container(), 153 | ), 154 | ], 155 | ), 156 | ), 157 | ); 158 | } 159 | } -------------------------------------------------------------------------------- /flutter/app/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.1" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.17.1" 44 | cupertino_icons: 45 | dependency: "direct main" 46 | description: 47 | name: cupertino_icons 48 | sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.5" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.1" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: "2118df84ef0c3ca93f96123a616ae8540879991b8b57af2f81b76a7ada49b2a4" 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "2.0.2" 73 | flutter_test: 74 | dependency: "direct dev" 75 | description: flutter 76 | source: sdk 77 | version: "0.0.0" 78 | http: 79 | dependency: "direct main" 80 | description: 81 | name: http 82 | sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "0.13.6" 86 | http_parser: 87 | dependency: transitive 88 | description: 89 | name: http_parser 90 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "4.0.2" 94 | js: 95 | dependency: transitive 96 | description: 97 | name: js 98 | sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "0.6.7" 102 | lints: 103 | dependency: transitive 104 | description: 105 | name: lints 106 | sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "2.1.1" 110 | matcher: 111 | dependency: transitive 112 | description: 113 | name: matcher 114 | sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.12.15" 118 | material_color_utilities: 119 | dependency: transitive 120 | description: 121 | name: material_color_utilities 122 | sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "0.2.0" 126 | meta: 127 | dependency: transitive 128 | description: 129 | name: meta 130 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.9.1" 134 | path: 135 | dependency: transitive 136 | description: 137 | name: path 138 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 139 | url: "https://pub.dev" 140 | source: hosted 141 | version: "1.8.3" 142 | sky_engine: 143 | dependency: transitive 144 | description: flutter 145 | source: sdk 146 | version: "0.0.99" 147 | source_span: 148 | dependency: transitive 149 | description: 150 | name: source_span 151 | sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.9.1" 155 | stack_trace: 156 | dependency: transitive 157 | description: 158 | name: stack_trace 159 | sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.11.0" 163 | stream_channel: 164 | dependency: transitive 165 | description: 166 | name: stream_channel 167 | sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "2.1.1" 171 | string_scanner: 172 | dependency: transitive 173 | description: 174 | name: string_scanner 175 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.2.0" 179 | term_glyph: 180 | dependency: transitive 181 | description: 182 | name: term_glyph 183 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "1.2.1" 187 | test_api: 188 | dependency: transitive 189 | description: 190 | name: test_api 191 | sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "0.5.1" 195 | typed_data: 196 | dependency: transitive 197 | description: 198 | name: typed_data 199 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "1.3.2" 203 | vector_math: 204 | dependency: transitive 205 | description: 206 | name: vector_math 207 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 208 | url: "https://pub.dev" 209 | source: hosted 210 | version: "2.1.4" 211 | sdks: 212 | dart: ">=3.0.6 <4.0.0" 213 | -------------------------------------------------------------------------------- /flutter/app/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: app 2 | description: Cats. 3 | # The following line prevents the package from being accidentally published to 4 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 5 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 6 | 7 | # The following defines the version and build number for your application. 8 | # A version number is three numbers separated by dots, like 1.2.43 9 | # followed by an optional build number separated by a +. 10 | # Both the version and the builder number may be overridden in flutter 11 | # build by specifying --build-name and --build-number, respectively. 12 | # In Android, build-name is used as versionName while build-number used as versionCode. 13 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 14 | # In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. 15 | # Read more about iOS versioning at 16 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 17 | # In Windows, build-name is used as the major, minor, and patch parts 18 | # of the product and file versions while build-number is used as the build suffix. 19 | version: 1.0.0+1 20 | 21 | environment: 22 | sdk: '>=3.0.6 <4.0.0' 23 | 24 | # Dependencies specify other packages that your package needs in order to work. 25 | # To automatically upgrade your package dependencies to the latest versions 26 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 27 | # dependencies can be manually updated by changing the version numbers below to 28 | # the latest version available on pub.dev. To see which dependencies have newer 29 | # versions available, run `flutter pub outdated`. 30 | dependencies: 31 | flutter: 32 | sdk: flutter 33 | http: ^0.13.3 34 | 35 | 36 | # The following adds the Cupertino Icons font to your application. 37 | # Use with the CupertinoIcons class for iOS style icons. 38 | cupertino_icons: ^1.0.2 39 | 40 | dev_dependencies: 41 | flutter_test: 42 | sdk: flutter 43 | 44 | # The "flutter_lints" package below contains a set of recommended lints to 45 | # encourage good coding practices. The lint set provided by the package is 46 | # activated in the `analysis_options.yaml` file located at the root of your 47 | # package. See that file for information about deactivating specific lint 48 | # rules and activating additional ones. 49 | flutter_lints: ^2.0.0 50 | 51 | # For information on the generic Dart part of this file, see the 52 | # following page: https://dart.dev/tools/pub/pubspec 53 | 54 | # The following section is specific to Flutter packages. 55 | flutter: 56 | 57 | # The following line ensures that the Material Icons font is 58 | # included with your application, so that you can use the icons in 59 | # the material Icons class. 60 | uses-material-design: true 61 | 62 | # To add assets to your application, add an assets section, like this: 63 | # assets: 64 | # - images/a_dot_burr.jpeg 65 | # - images/a_dot_ham.jpeg 66 | 67 | # An image asset can refer to one or more resolution-specific "variants", see 68 | # https://flutter.dev/assets-and-images/#resolution-aware 69 | 70 | # For details regarding adding assets from package dependencies, see 71 | # https://flutter.dev/assets-and-images/#from-packages 72 | 73 | # To add custom fonts to your application, add a fonts section here, 74 | # in this "flutter" section. Each entry in this list should have a 75 | # "family" key with the font family name, and a "fonts" key with a 76 | # list giving the asset and other descriptors for the font. For 77 | # example: 78 | # fonts: 79 | # - family: Schyler 80 | # fonts: 81 | # - asset: fonts/Schyler-Regular.ttf 82 | # - asset: fonts/Schyler-Italic.ttf 83 | # style: italic 84 | # - family: Trajan Pro 85 | # fonts: 86 | # - asset: fonts/TrajanPro.ttf 87 | # - asset: fonts/TrajanPro_Bold.ttf 88 | # weight: 700 89 | # 90 | # For details regarding fonts from package dependencies, 91 | # see https://flutter.dev/custom-fonts/#from-packages 92 | -------------------------------------------------------------------------------- /flutter/app/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:app/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /kmp/cats/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | build/ -------------------------------------------------------------------------------- /kmp/cats/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /kmp/cats/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("android") 3 | id("com.android.application") 4 | id("org.jetbrains.compose") 5 | } 6 | 7 | android { 8 | namespace = "com.example.cats" 9 | compileSdk = 34 10 | 11 | defaultConfig { 12 | applicationId = "com.example.cats" 13 | minSdk = 21 14 | targetSdk = 34 15 | versionCode = 1 16 | versionName = "1.0" 17 | 18 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 19 | vectorDrawables { 20 | useSupportLibrary = true 21 | } 22 | } 23 | 24 | buildTypes { 25 | release { 26 | isMinifyEnabled = true 27 | isShrinkResources = true 28 | signingConfig = signingConfigs.getByName("debug") 29 | proguardFiles( 30 | getDefaultProguardFile("proguard-android-optimize.txt"), 31 | "proguard-rules.pro" 32 | ) 33 | } 34 | create("benchmark") { 35 | initWith(buildTypes.getByName("release")) 36 | matchingFallbacks += listOf("release") 37 | isDebuggable = false 38 | } 39 | } 40 | compileOptions { 41 | sourceCompatibility = JavaVersion.VERSION_17 42 | targetCompatibility = JavaVersion.VERSION_17 43 | } 44 | composeOptions { 45 | kotlinCompilerExtensionVersion = "1.5.3" 46 | } 47 | buildFeatures { 48 | compose = true 49 | } 50 | packaging { 51 | resources { 52 | excludes += "/META-INF/{AL2.0,LGPL2.1}" 53 | } 54 | } 55 | } 56 | 57 | dependencies { 58 | implementation("androidx.core:core-ktx:1.10.1") 59 | implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") 60 | implementation("androidx.activity:activity-compose:1.7.2") 61 | implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") 62 | 63 | implementation(project(":shared")) 64 | } -------------------------------------------------------------------------------- /kmp/cats/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -dontwarn org.slf4j.impl.StaticLoggerBinder 23 | -keep class io.kamel.** { *; } -------------------------------------------------------------------------------- /kmp/cats/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/java/com/example/cats/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.cats 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import com.sample.cats.ui.CatsApp 7 | 8 | class MainActivity : ComponentActivity() { 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | setContent { 13 | CatsApp() 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 10 | 16 | 19 | 22 | 23 | 24 | 25 | 31 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jacobras/flutter-vs-native-vs-kmp/10b4bc8ff32f2550f3d87a7585e39e3dc89e2843/kmp/cats/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Cats 3 | -------------------------------------------------------------------------------- /kmp/cats/app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |