本文運(yùn)行環(huán)境說(shuō)明: Flutter (Channel unknown, v1.9.1+hotfix.2, on Mac OS X 10.12.6 16G2128, locale zh-Hans-CN)
創(chuàng)建 flutter module 工程
Flutter create -t module flutter_library
- 這種方式創(chuàng)建的 flutter 項(xiàng)目常常用來(lái)集成到現(xiàn)有 Android 或 ios 工程中爱沟,對(duì)于 Android 工程抹竹,我們希望的是將 flutter 工程打包成一個(gè) aar 文件,放入 Android 項(xiàng)目中繼承坚芜,本文就介紹一下打包集成方式屉佳。
將 flutter 打包成 aar
打包命令分析
從 flutter 1.9.1開(kāi)始谷朝,支持直接打包為 aar,命令為
flutter build aar
如果想輸出詳細(xì)打包過(guò)程日志忘古,可以在后面加上 -v 參數(shù)
使用 which flutter 命令可以找到 flutter 的命令文件徘禁,查看該文件,能找到真正執(zhí)行的命令髓堪。不是很清楚 shell 腳本的話看起來(lái)比較費(fèi)勁送朱,這里直接說(shuō)結(jié)論吧:命令采用了 dart 執(zhí)行環(huán)境,編譯打包邏輯在 flutter_tools.snapshot 中干旁。dart 的 snapshot 相當(dāng)于 Java 的 jar驶沼,因此,一個(gè) snapshot 在執(zhí)行的時(shí)候争群,必然有它的執(zhí)行入口回怜,也就是類(lèi)似 main 函數(shù)的東西。這里的入口换薄,正是 flutter/packages/flutter_tools/bin/flutter_tools.dart 玉雾,其 main 函數(shù)如下:
void main(List<String> args) {
executable.main(args);
}
進(jìn)入 executable.dart,在 main 方法中可以看到創(chuàng)建了一堆 xxxCommand 對(duì)象轻要,顯然這是各種命令對(duì)應(yīng)的類(lèi)复旬,我們暫時(shí)只需要關(guān)心 flutter build 命令匹配的 BuildCommand() 方法。
class BuildCommand extends FlutterCommand {
BuildCommand({bool verboseHelp = false}) {
addSubcommand(BuildAarCommand(verboseHelp: verboseHelp));
addSubcommand(BuildApkCommand(verboseHelp: verboseHelp));
addSubcommand(BuildAppBundleCommand(verboseHelp: verboseHelp));
addSubcommand(BuildAotCommand(verboseHelp: verboseHelp));
addSubcommand(BuildIOSCommand());
addSubcommand(BuildBundleCommand(verboseHelp: verboseHelp));
addSubcommand(BuildWebCommand());
addSubcommand(BuildMacosCommand(verboseHelp: verboseHelp));
addSubcommand(BuildLinuxCommand());
addSubcommand(BuildWindowsCommand());
addSubcommand(BuildFuchsiaCommand(verboseHelp: verboseHelp));
}
@override
final String name = 'build';
@override
final String description = 'Flutter build commands.';
@override
Future<FlutterCommandResult> runCommand() async => null;
}
abstract class BuildSubCommand extends FlutterCommand {
BuildSubCommand() {
requiresPubspecYaml();
}
}
這里定義的一系列子命令冲泥,正是對(duì)應(yīng)了我們運(yùn)行 flutter build -h 所看到的內(nèi)容驹碍。
通過(guò)與父類(lèi)的一系列調(diào)用關(guān)系,最終調(diào)用子類(lèi)真正的 runCommand 的方法凡恍,由于這里執(zhí)行的是 build aar志秃,所以子類(lèi)是BuildAarCommand。
一番追蹤之后嚼酝,你會(huì)發(fā)現(xiàn)最終還是調(diào)用了 android 的 gradlew assembleRelease 命令浮还,只是加入了一些參數(shù)而已。然后闽巩,繼續(xù)追蹤 flutter 工程的 .android 目錄下的 gradle 文件碑定。
.android 目錄下有兩個(gè)重要的 gradle 文件流码,一個(gè)是 include_flutter.groovy又官,另一個(gè)是 Flutter 目錄下的 build.gradle延刘。
前者的主要作用是編譯 Flutter 目錄和插件,后者檢查了 flutter sdk 版本信息六敬,然后進(jìn)入了 flutter.gradle碘赖,它是一個(gè) gradle 插件,里面實(shí)現(xiàn)了一些 task 以及設(shè)定了必要的依賴(lài)外构;
至于后續(xù)的打包過(guò)程還沒(méi)有搞清楚普泡,各位客官自己研究分析吧。
打包產(chǎn)物分析
打包命令運(yùn)行后生成的產(chǎn)物被放在 build 目錄下的不同文件夾里审编,我們主要關(guān)心 aar撼班,它被放在 build/host/outputs/repo 文件夾,包括 flutter 主項(xiàng)目及每一個(gè) flutter 插件對(duì)應(yīng)的 aar垒酬,分別放在以主項(xiàng)目或插件包名對(duì)應(yīng)路徑下砰嘁。介紹如下:
flutter_release.aar:類(lèi)似這個(gè)名稱(chēng)的文件是 flutter 主項(xiàng)目對(duì)應(yīng)生成的 aar,解壓 aar 文件勘究,里面的內(nèi)容介紹:
- jni:生成有 libflutter.so 和 libapp.so矮湘,這兩個(gè) Flutter 庫(kù)和引擎、Dart VM 以及 dart 業(yè)務(wù)代碼(這里指你自己寫(xiě)的代碼邏輯)編譯后的產(chǎn)物口糕,從此可以看出缅阳,F(xiàn)lutter 庫(kù)和引擎會(huì)被打包成 so 文件并最終匯總到 apk 中,以給 flutter 提供運(yùn)行時(shí)環(huán)境景描;
- assets:存放了 flutter 項(xiàng)目的資源文件十办,例如圖片、自定義字體等超棺;
- libs: 含有 flatter.jar向族,主要是官方已經(jīng)寫(xiě)好的、flutter 與 Android 通信的邏輯類(lèi)说搅,比如 FlutterActivity炸枣、MethodCall 等;
- .classes.jar: Flutter.java弄唧、FlutterFragment.java适肠、GeneratedPluginRegistrant.java的 class 文件,其實(shí)就是對(duì)應(yīng) .android/Flutter/src 目錄下的代碼;其他包里的 aar: 對(duì)應(yīng)的是插件打包成的 aar候引,解壓該 aar 文件侯养,會(huì)看到插件的 Android 部分源碼打在了 aar 里的 classes.jar 中,資源文件放在了 res 目錄下澄干;
將所有產(chǎn)物匯總成一個(gè) aar
- 方便起見(jiàn)逛揩,最好是將上面的主工程 aar 和每個(gè)插件的 aar 一起打到一個(gè) aar 中柠傍,這個(gè) aar 就可以放在其他 Android 工程中使用了;
- 如果想將多個(gè) aar 匯總成一個(gè) aar辩稽,可以借助 fat-aar-android惧笛;
附
- 清除緩存: 命令:flutter clean,這樣會(huì)清楚 build 目錄逞泄,另外要說(shuō)明的是患整,這樣也會(huì)清空 .android 目錄,當(dāng)執(zhí)行 flutter packages get 后又會(huì)自動(dòng)生成 .android 目錄喷众;