Flutter 混合开发指南:项目打包与原生 Android/iOS 集成

在移动开发中,将 Flutter 集成到现有的原生 Android 或 iOS 项目中是一种常见的混合开发模式(Add-to-App)。这种方式允许开发者在保留现有原生业务的同时,利用 Flutter 高效构建新的 UI 模块。

本文将详细介绍如何创建一个 Flutter Module,将其打包为库文件,并在原生 Android 和 iOS 项目中进行集成。

1. 创建 Flutter Module

首先,我们需要创建一个 Flutter Module 项目,而不是标准的 Flutter App。Module 项目专门用于嵌入到宿主应用中。

在终端中运行以下命令:

复制代码
flutter create -t module my_flutter_module

这将创建一个名为 my_flutter_module 的目录。该项目的结构与普通 Flutter 项目略有不同,它包含 .android 和 .ios 隐藏目录,用于辅助构建。


2. Android 项目打包与集成

Android 平台通常使用 AAR (Android Archive) 包的方式进行集成。

2.1 打包 AAR

进入 Flutter Module 根目录,执行构建命令:

复制代码
cd my_flutter_module
flutter build aar

构建成功后,终端会输出具体的集成指引,通常包含以下信息:

  1. AAR 产物的路径(通常在 build/host/outputs/repo)。
  2. 需要在宿主 Android 项目中添加的 Gradle 配置。

2.2 宿主项目配置 (Android)

打开你的原生 Android 项目,修改 build.gradle 文件。

第一步:添加本地仓库路径

在项目级 build.gradle (Project level) 或 settings.gradle 中,将 Flutter 构建的本地仓库添加到 repositories 块中:

Groovy 复制代码
// settings.gradle 或 build.gradle
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        // 添加这一行,路径指向 Flutter Module 的 repo 目录
        maven { url 'path/to/my_flutter_module/build/host/outputs/repo' }
    }
}

第二步:添加依赖

在应用级 build.gradle (App level, 通常是 app/build.gradle) 中添加依赖:

Groovy 复制代码
dependencies {
    // 添加 debug 模式依赖
    debugImplementation 'com.example.my_flutter_module:flutter_debug:1.0'
    // 添加 profile 模式依赖 (用于性能分析)
    profileImplementation 'com.example.my_flutter_module:flutter_profile:1.0'
    // 添加 release 模式依赖
    releaseImplementation 'com.example.my_flutter_module:flutter_release:1.0'
}

注:具体的 groupId(com.example.my_flutter_module) 可以在 Flutter Module 的 pubspec.yaml中配置,或者查看 flutter build aar的输出日志。

2.3 Android 代码接入

为了提升启动速度,建议在 Application 启动时预热 FlutterEngine。

在 Application 类中初始化:

java 复制代码
// MyApplication.java
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;

public class MyApplication extends Application {
    public FlutterEngine flutterEngine;

    @Override
    public void onCreate() {
        super.onCreate();

        // 1. 实例化 FlutterEngine
        flutterEngine = new FlutterEngine(this);

        // 2. 配置初始路由(可选)并执行 Dart 代码
        flutterEngine.getNavigationChannel().setInitialRoute("/");
        flutterEngine.getDartExecutor().executeDartEntrypoint(
            DartExecutor.DartEntrypoint.createDefault()
        );

        // 3. 将 FlutterEngine 存入缓存,使用 ID "my_engine_id"
        FlutterEngineCache
            .getInstance()
            .put("my_engine_id", flutterEngine);
    }
}

启动 Flutter 页面:

java 复制代码
// 在 Activity 或 Fragment 中启动
import io.flutter.embedding.android.FlutterActivity;

startActivity(
    FlutterActivity
        .withCachedEngine("my_engine_id")
        .build(currentActivity)
);

3. iOS 项目打包与集成

iOS 平台通常将 Flutter 打包为 XCFramework 或 Framework 进行集成。

3.1 打包 Framework

在 Flutter Module 根目录下运行:

bash 复制代码
flutter build ios-framework --output=./flutter_frameworks

该命令会在 flutter_frameworks 目录下生成三种构建模式的产物:

  • Debug/:包含调试功能的 Framework,体积较大,用于开发。
  • Profile/:用于性能分析。
  • Release/:用于正式发布。

每个目录下通常包含:

  • App.xcframework:包含你的 Dart 代码和资源。
  • Flutter.xcframework:Flutter 引擎。
  • 以及其他依赖插件的 Framework。

3.2 宿主项目配置 (iOS)

  1. 打开 Xcode 项目。
  2. 根据当前的构建配置(Debug 或 Release),将对应的 App.xcframework 和 Flutter.xcframework (以及其他插件 Framework) 拖入到工程导航栏中。
  3. 选中你的 Target,进入 General -> Frameworks, Libraries, and Embedded Content。
  4. 确保导入的 Frameworks 的 Embed 选项被设置为 Embed & Sign。

注意:在实际开发中,为了方便切换 Debug/Release,通常会使用 CocoaPods 脚本来动态引入不同模式的 Framework,或者在 Build Phases 中添加脚本处理。

3.3 iOS 代码接入

同样建议在 AppDelegate 中预热引擎。

在 AppDelegate 中初始化:

Swift 复制代码
// AppDelegate.swift
import UIKit
import Flutter
import FlutterPluginRegistrant // 如果使用了插件

@UIApplicationMain
class AppDelegate: FlutterAppDelegate { // 继承自 FlutterAppDelegate
    
    lazy var flutterEngine = FlutterEngine(name: "my_engine_id")

    override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // 1. 运行 Flutter 引擎
        flutterEngine.run();
        
        // 2. 注册插件(如果需要)
        GeneratedPluginRegistrant.register(with: flutterEngine);
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions);
    }
}

启动 Flutter 页面:

Swift 复制代码
// 在 ViewController 中
import Flutter

func showFlutter() {
    // 获取 AppDelegate 中的引擎
    let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
    
    // 创建 FlutterViewController
    let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
    
    // 跳转
    self.present(flutterViewController, animated: true, completion: nil)
}

4. 总结

通过 Flutter Module,我们可以灵活地将 Flutter 页面嵌入到现有的原生应用中。

  • Android :核心是通过 flutter build aar 生成本地 Maven 仓库,利用 Gradle 依赖管理进行集成。
  • iOS :核心是通过 flutter build ios-framework 生成 Framework 产物,通过手动嵌入或 CocoaPods 集成。
  • 性能优化 :无论哪种平台,使用 FlutterEngineCache 预热引擎都是提升首屏打开速度的关键步骤。
相关推荐
2501_915106329 分钟前
KXApp 的 VS Code 真机调试:按下 Cmd+R 之后发生了什么
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
大熊的瓜地24 分钟前
从0开始写android -完结篇
android
扶尔魔ocy32 分钟前
【QT android】模仿行车记录仪案例
android·qt
看我debug36 分钟前
Android 运行时分析工作台 (Demo)。统一管理 Frida 脚本、自动注入(修改运行时代码)、收集结构化结果、生成 JSON 报告。
android·python·pip
通信侠40 分钟前
android 13重启清除任务快照
android
小铁-Android1 小时前
CompletableDeferred:Kotlin 协程中用于一次性挂起通信的工具
android·kotlin
恋猫de小郭1 小时前
Flutter 的文字为什么比 SwiftUI 更细?问题主要在 Skia 的 256 项查找表里
android·前端·flutter
ii_best1 小时前
安卓手机开发、iOS 手机开发都能用:按键精灵远程调试,设备在千里外也能改脚本
android·ios·智能手机·自动化·按键精灵
stevenzqzq4 小时前
Android Jetpack Compose 列表开发指南:为什么你不需要再为底部 Item 写额外间距
android·android jetpack
撩得Android一次心动12 小时前
Jetpack Compose 知识点整理2【个人用】
android·笔记·学习·kotlin·compose