Flutter Analysis and Practice: Hybrid Projects and Continuous Integration

1.3.1 Background

1) If the Flutter project structure is directly used for daily development, native project developers also need to set up the Flutter environment and understand the Flutter technology, which increases costs.

2) Currently, Alibaba Group’s building system does not support direct building of Flutter projects. This requires Xianyu to remove native project dependencies on Flutter.

From this perspective, Xianyu wants to design a module to extract Flutter dependencies as a Flutter dependency library and publish it to the remote repository for reference by native projects, as shown in Figure 1–16.

1.3.2 Implementation Methods Analyze Flutter Projects That Native Projects Depend On

Based on Flutter project analysis, native projects depend on Flutter as follows:

  • Flutter library and engine files, including the framework library and engine library of Flutter.
  • Flutter projects, which can be packaged as an AAR file for reference. Custom Flutter module features are implemented through Dart code in the lib directory.
  • Custom Flutter plug-ins

Major Flutter dependency files are extracted from the app packages of Android and iOS, as shown in Figure 1–17.

1) Flutter dependency files for Android

  • Flutter library and engine files, including icudtl.dat, libflutter.so, and some class files. They are all encapsulated in flutter.jar, which is in flutter/bin/cache/artifacts/engine in the Flutter library directory.
  • Flutter project outputs, including isolate_snapshot_data, isolate_snapshot_instr, vm_snapshot_data, vm_snapshot_instr, and flutter_assets.
  • Flutter plug-ins. Android Archive (AAR) files compiled by each plug-in include: isolate_snapshot_data (app data segments), isolate_snapshot_instr (app instruction segments), vm_snapshot_data (virtual machine data segments), and vm_snapshot_instr (virtual machine instruction segments.)

2) Flutter dependency files for iOS

  • Flutter library and engine files, including Flutter.framework.
  • Flutter project outputs, including App.framework.
  • Flutter plug-ins, including frameworks of each compiled plug-in and other frameworks show in Figure 1–17.

The compilation results need to be extracted and packaged into a Software Development Kit (SDK) dependency for the native project, which removes native project dependencies on the Flutter project. Extract the Flutter Library Android Depends On

1) Analyze the Flutter compilation task on Android

Android packaging of the Flutter project is to insert a flutter.gradle task to the Android Gradle task. The flutter.gradle task (this file can be found in the flutter/packages/flutter_tools/gradle directory in the Flutter library) implements the following operations:

  • Add the flutter.jar dependency.
  • Add the compilation dependency of Flutter plug-ins.
  • Add the compilation task of the Flutter project. The output includes two isolate_snapshot files, two vm_snapshots files, and the flutter_assets folder. Copy the compiled project to mergeAssets.outputDir and then save it to the assets directory of the Android Package Kit (APK.)

2) Implement Flutter dependency extraction on Android

Perform the following steps:

(a) Compile a Flutter project.

This aims to compile Flutter’s Dart code and resources by running the ahead-of-time (AOT) and Bundle commands.

(b) Package flutter.jar and the output of the Flutter project into an AAR file.

This aims to encapsulate flutter.jar and the output compiled in step 1 into an AAR file.

Add the flutter.jar dependency.

Merge the output of the Flutter project into assets.

© Publish the output AAR file and the AAR file compiled by Flutter plug-ins to the Maven repository.

Publish the AAR file of the Flutter project output.

Publish the AAR file of Flutter plug-ins.

(d) Native projects only need to depend on the AAR files published to the Maven repository.

During the development, the latest AAR files are required in real time. Therefore, the snapshot version is used.

1.3.3 Extract the Flutter Library That iOS Depends On Generate Flutter Dependency Files on iOS

Run the flutter build ios command. The Flutter compilation script xcode_backend.sh is finally run to:

Obtain various parameters, such as project_path, target_path, and build_mode, which are defined in Generated.xcconfig.

Delete the App.framework and app.flx files from the Flutter directory.

Compare Flutter/Flutter.framework with Flutter.framework in the FLUTTER_ROOT/bin/cache/artifacts/engine {artifact_variant} directory. If they are different, use Flutter.framework in the directory to overwrite the former.

Obtain the parameters for generating App.framework, including build_dir, local_engine_flag, preview_dart_2_flag, and aot_flags.

Generate the App.framework file and replicate it and the AppFrameworkInfo.plist file to the Flutter directory of the Xcode project. Implement Flutter Dependency Extraction on iOS

Compile the Flutter project to generate the App.framework file.

Package all plug-ins as static libraries: Package the plug-ins into a binary library file, and then package the registration portals of the plug-ins into a binary library file.

Upload these files to the remote repository and generate new tags. Update pod dependencies for native projects.

1.3.4 Continuous Integration Process of the Flutter Hybrid Project

The following problems still exist in daily development:

  • The Flutter project is updated, but the remote dependency library is not updated in time.
  • During version integration, the remote dependency library is not updated, causing the failure to integrate the latest Flutter features in the version.
  • When Flutter is developed in parallel, versioning is confused and the remote library may be overwritten.
  • At least one developer needs to follow up on the publishing, increasing the labor cost.

Therefore, Xianyu has introduced the automatic framework of CI to solve these problems. It reduces the labor cost and manual errors through automation. In addition, it implements auto versioning.

First, before a native project is built each time, the remote library of the Flutter project is automatically compiled and released, without any manual intervention throughout the process. Second, during development and testing, five-digit version numbers in A.B.C.D.X format are used, with the last digit incremented automatically. This ensures that all versions of the Flutter library developed in parallel do not conflict with each other. Finally, in the publishing phase, three-digit (A.B.C) or four-digit (A.B.C.D) version numbers are used to match the app version number, which facilitates tracing of subsequent issues.

Figure 1–18 shows the entire process.

Original Source:

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.