前言
- 隨著Flutter release版本的發(fā)布,F(xiàn)lutter的使用也提上日程,但是對(duì)于已有項(xiàng)目來說,直接使用Flutter重寫不太現(xiàn)實(shí),所以需要在現(xiàn)有native項(xiàng)目中集成Flutter
集成步驟
- flutter環(huán)境的搭建以及flutter項(xiàng)目的創(chuàng)建就不再贅述了,網(wǎng)上也有許多非常詳細(xì)的教程(這里給個(gè)傳送門)
- 首先打開需要集成flutter的Android項(xiàng)目的Terminal面板,執(zhí)行以下命令:
flutter create -t module flutter_yxj_user
其中flutter_yxj_user為你的flutter module 名
打開cmd切換到需要集成flutter的Android項(xiàng)目的同級(jí)目錄執(zhí)行以上命令也可以,另外AS最新版本[當(dāng)前是3.2.1]中,注意需要最新版本才可以,用舊版本的無法利用該方法,只能使用命令行的方式,直接File->New->New Flutter Project->Flutter Module創(chuàng)建
-
執(zhí)行上述命令后會(huì)在需要集成flutter的Android項(xiàng)目的同級(jí)目錄生成一個(gè)Flutter Module "your_flutter_module_name",可以看到項(xiàng)目中的.android文件夾中有一個(gè)include_flutter.groovy文件
flutter_module_目錄 生成Module之后,在Android項(xiàng)目中的settings.gradle中添加如下配置代碼,其中new File的參數(shù)就是include_flutter.groovy的路徑,你可以寫死,也可以動(dòng)態(tài)配置,比如在local.properties文件中或和其它常量統(tǒng)一配置
//加入下面配置
setBinding(new Binding([gradle: this]))
evaluate(new File(
"settingsDir.parentFile", //這里是你的flutter module生成的目錄dir,這里這樣寫代表需要集成flutter的Android項(xiàng)目的根目錄,如果你的flutter module創(chuàng)建在其它目錄,請(qǐng)?jiān)谶@里修改,如我這里的("E://flutter_workspaces")
'flutter_yxj_user/.android/include_flutter.groovy' //這個(gè)是include_flutter.groovy文件的路徑
))
- 需要集成flutter的Android項(xiàng)目的app 的build.gradle文件中dependencies塊中引入flutter project,同步一下即完成引入
implementation project(':flutter')
同步之后可以看到在Android項(xiàng)目的同級(jí)目錄中出現(xiàn)了一個(gè)名為Flutter的mudule
-
集成之后的項(xiàng)目結(jié)構(gòu)如下:
集成flutter的Android工程結(jié)構(gòu)目錄
可以看到出現(xiàn)的Flutter的映射路徑實(shí)際上就是上面我們生成的flutter module里面的.android目錄中的Flutter。所以我們也可以猜測(cè)一下,添加的配置代碼實(shí)際上就是在gradle的初始化階段執(zhí)行include_flutter.groovy文件中的代碼,而這個(gè)文件代碼的作用就是將剛剛生成的flutter module的的Flutter目錄加載到項(xiàng)目中,建立一個(gè)映射關(guān)系。加載進(jìn)來的和利用命令生成的目錄是同一個(gè)。做一個(gè)小測(cè)試,在加載進(jìn)來的Flutter目錄下生成一個(gè)文件,在生成的目錄下也會(huì)生成該文件更加證實(shí)了我們的猜想。
對(duì)這部分感興趣的同學(xué)也可以查看一下include_flutter.groovy文件中的代碼
// Generated file. Do not edit.
//獲取include_flutter.groovy文件的路徑
def scriptFile = getClass().protectionDomain.codeSource.location.path
//獲取flutter Project的根目錄,也就是剛剛生成的flutter module的目錄
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile
//引入項(xiàng)目flutter,這里也可以看出我們?cè)赼pp 的build.gradle引入Flutter時(shí)是flutter而不是別的
gradle.include ':flutter'
//設(shè)置project flutter的projectDir為剛剛生成的flutter module的目錄下的.android/Flutter目錄
gradle.project(':flutter').projectDir = new File(flutterProjectRoot, '.android/Flutter')
def plugins = new Properties()
//拿到flutterProjectRoot目錄下的.flutter-plugins文件,該文件存在于flutter插件module,也就是說你的flutter module中還存在Flutter Plugin項(xiàng)目,里面的內(nèi)容類似于“flutter_plugin=E:\\flutter_workspaces\\hello_flutter\\flutter_plugin\\”
def pluginsFile = new File(flutterProjectRoot, '.flutter-plugins')
if (pluginsFile.exists()) {
//如果該文件存在,讀取property list到Properties plugins中,以key - value的形式,當(dāng)前該文件是不存在的
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
//如果存在插件的話,引入
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.toPath().resolve(path).resolve('android').toFile()
gradle.include ":$name"
gradle.project(":$name").projectDir = pluginDirectory
}
//為項(xiàng)目的所有非flutter子module添加依賴,依賴flutter module
gradle.getGradle().projectsLoaded { g ->
//為項(xiàng)目的根project添加生命周期監(jiān)聽,在gradle配置階段之后執(zhí)行
g.rootProject.afterEvaluate { p ->
//遍歷所有的子 project(也就是module)
p.subprojects { sp ->
if (sp.name != 'flutter') {
//如果該項(xiàng)目不是flutter module,添加依賴
sp.evaluationDependsOn(':flutter')
}
}
}
}
- 如果對(duì)于groovy語法不熟悉的同學(xué),也可以查看筆者的gradle系列文章