Android原生項(xiàng)目集成Flutter解決方案
了解一下如何在 Android 原生項(xiàng)目中集成 Flutter
生成配置
在原生項(xiàng)目根目錄執(zhí)行命令
flutter create -t module --org {package_name} {module_name}
// 此處 module_name 的命令遵循 Android 子 module 的命名即可。不能有中劃線。
// 比如,
flutter create -t module --org com.engineer.mini.flutter flutter_sub
// 此處 module_name 的命令遵循 Android 子 module 的命名即可。不能有中劃線。
// 比如,
flutter create -t module --org com.engineer.mini.flutter flutter_sub
</pre>
結(jié)果
Creating project sub_flutter...
sub_flutter/test/widget_test.dart (created)
sub_flutter/sub_flutter.iml (created)
sub_flutter/.gitignore (created)
sub_flutter/.metadata (created)
sub_flutter/pubspec.yaml (created)
sub_flutter/README.md (created)
sub_flutter/lib/main.dart (created)
sub_flutter/sub_flutter_android.iml (created)
sub_flutter/.idea/libraries/Dart_SDK.xml (created)
sub_flutter/.idea/modules.xml (created)
sub_flutter/.idea/workspace.xml (created)
Running "flutter pub get" in sub_flutter... 1,054ms
Wrote 11 files.
最終生成了以上文件,注意這里最后 自動(dòng)執(zhí)行了 flutter pub get 的命令。關(guān)于 flutter pub get 具體做了什么,可以參考后面的。
這里在項(xiàng)目根目錄創(chuàng)建子 module 只是為了把代碼放在一個(gè)倉(cāng)庫(kù),方便維護(hù),理論上可以放在硬盤(pán)的任何位置。
配置原生項(xiàng)目 settings.gradle
在配置 settings.gradle 之前先來(lái)簡(jiǎn)單回顧一下關(guān)于 Gradle 的一些基礎(chǔ)知識(shí)。
如果你了解過(guò) Gradle 相關(guān)的配置的話,一定會(huì)看到一個(gè)概念,就是 約定優(yōu)于配置 ,什么意思呢,按照面向?qū)ο蟮乃悸穪?lái)理解,每一個(gè)工程是一個(gè)巨大的 Project 類(lèi),整個(gè)類(lèi)里有很多的屬性。而我們創(chuàng)建的每一個(gè)項(xiàng)目其實(shí)就是一個(gè)具體的 Project 對(duì)象(也就是實(shí)例).約定優(yōu)于配置的意思,就是在 project 實(shí)例化的時(shí)候,其內(nèi)部的屬性已經(jīng)有了默認(rèn)值。那么我們?cè)趺粗烙心男┠J(rèn)值呢?在項(xiàng)目根目錄執(zhí)行
./gradlew properties
就可以得到整個(gè) Project 的一些默認(rèn)配置,比如(此處節(jié)選部分結(jié)果)
------------------------------------------------------------ Root project ------------------------------------------------------------ allprojects: [root project 'MiniApp', project ':app', project ':thirdlib'] android.agp.version.check.performed: true android.enableJetifier: true android.enableR8: true android.enableR8.libraries: true android.useAndroidX: true buildDir: /Users/username/Documents/mygithub/MinApp/build buildFile: /Users/username/Documents/mygithub/MinApp/build.gradle projectDir: /Users/username/Documents/mygithub/MinApp rootDir: /Users/username/Documents/mygithub/MinApp rootProject: root project 'MiniApp'
這里當(dāng)前有一些是我們配置的,比如 useAndroidX,但也有一些是約定的,比如 對(duì)于整個(gè) project 來(lái)說(shuō) buildDir 就是項(xiàng)目根目錄的 build 文件夾等。
執(zhí)行
./gradlew :app:properties
節(jié)選部分結(jié)果
buildDir: /Users/username/Documents/mygithub/MinApp/app/build buildFile: /Users/username/Documents/mygithub/MinApp/app/build.gradle
就會(huì)得到關(guān)于 app 整個(gè) module 現(xiàn)階段的一些配置信息,當(dāng)然這些配置信息除了約定的,還有你自己配置的,比如 buildToolsVersion ,簽名等相關(guān)信息??梢钥吹?buildDir 和整個(gè) project 的是不一樣的。
回到主題, 看看如何把我們剛才創(chuàng)建的 sub_flutter 模塊集成到項(xiàng)目中。(嚴(yán)格來(lái)說(shuō)并不是集成 sub_flutter 模塊,因?yàn)樗皇且粋€(gè) flutter 的模塊,而在 Android 主項(xiàng)目只能集成子 Android module,那么具體改怎么做呢,下面就來(lái)看看其中的奧秘)
按照官方的操作方法,會(huì)要求我們添加以下配置到 settings.gradle 中。
// Include the host app project. include ':app' // assumed existing content setBinding(new Binding([gradle: this])) // new evaluate(new File( // new settingsDir.parentFile, // new 'my_flutter/.android/include_flutter.groovy' // new )) // new
首先看看 這里的 settingsDir 的值。在 settings.gradle 中直接添加
println "settings.dir=" + settingsDir println "settings.dir.parent=" + settingsDir.parent
sync 之后就會(huì)看到輸出
settings.dir=/Users/username/Documents/mygithub/MinApp settings.dir.parent=/Users/username/Documents/mygithub
所以,上面的配置信息,就是說(shuō)結(jié)合 settings 所在目錄的父目錄和我們配置的目錄結(jié)合,找到一個(gè)名為 include_flutter.groovy 的文件,然后去執(zhí)行他。
前面說(shuō)了,創(chuàng)建子 module 的時(shí)候,可以是在項(xiàng)目根目錄,也可以是在其他位置,如果是在其他位置,這里的 my_flutter 可以替換為你創(chuàng)建目錄的絕對(duì)路勁。
這里是在根目錄直接創(chuàng)建的,那么以上的配置就可以簡(jiǎn)化為
setBinding(new Binding([gradle: this])) evaluate(new File(settingsDir, 'sub_flutter/.android/include_flutter.groovy')) include ':sub_flutter' #### 關(guān)于 include_flutter.groovy
上面說(shuō)了,settings.gradle 的配置,其實(shí)就是去執(zhí)行 include_flutter.groovy 這個(gè)文件,可以簡(jiǎn)單看一下這個(gè)文件
def scriptFile = getClass().protectionDomain.codeSource.location.toURI()
def flutterProjectRoot = new File(scriptFile).parentFile.parentFile
gradle.include ":flutter"
gradle.project(":flutter").projectDir = new File(flutterProjectRoot, ".android/Flutter")
def localPropertiesFile = new File(flutterProjectRoot, ".android/local.properties")
def properties = new Properties()
assert localPropertiesFile.exists(), ":exclamation:️The Flutter module doesn't have a `$localPropertiesFile` file." +
"\nYou must run `flutter pub get` in `$flutterProjectRoot`."
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
gradle.apply from: "$flutterSdkPath/packages/flutter_tools/gradle/module_plugin_loader.gradle"
.android 其實(shí)就是一個(gè) Android 項(xiàng)目,他包含一個(gè) Flutter 文件夾,這 Flutter 是一個(gè) library 類(lèi)型的 Android module ,這個(gè)一點(diǎn)從他的 build.gradle 文件就可以看出。 include_flutter.groovy 所做的事情,就是將當(dāng)前 library 命名為 flutter 的一個(gè) moudle。然后檢查項(xiàng)目中 local.properties 中 sdk 的相關(guān)配置,最后去執(zhí)行 FlutterSDK 的中 gradle 腳本,這里具體的分析就不再展開(kāi)了。
也就是說(shuō),現(xiàn)在有一個(gè)名為 flutter 的 Android Library Module 。這個(gè) module 包含 flutter 的所有配置。我們?nèi)绻蕾嚵诉@個(gè) module ,那么就相當(dāng)于是依賴了 Flutter .
依賴 flutter
最后在原生項(xiàng)目的 application-module 的 build.gradle 的 dependencies 閉包中添加
implementation project(':flutter')
至此,原生項(xiàng)目已經(jīng)有了 Flutter 的依賴,可以使用 Flutter 的 View 了。
至此,現(xiàn)在的原生項(xiàng)目就包含 Flutter SDK 的所有依賴了,UI 相關(guān)的內(nèi)容,改怎么寫(xiě)還是用 dart 在 main.dart 中寫(xiě),然后我們就可以把這個(gè) dart 渲染出來(lái)的內(nèi)容按照 Activity 、Fragment 或 View 的形式添加到已有的項(xiàng)目中了。
flutter pub get
flutter pub get 或者 pub get 是在做 flutter 的時(shí)候在使用第三方 lib 或版本更新的時(shí)候經(jīng)常會(huì)使用一個(gè)命令,通過(guò)這個(gè)命令會(huì)拉取相關(guān)的依賴,其實(shí)這個(gè)命令還會(huì)自動(dòng)生成 Android 和 iOS 的原生項(xiàng)目。比如在我們創(chuàng)建就的 sub_flutter 模塊中,均自動(dòng)生成了 .android 和 .ios 的原生項(xiàng)目目錄。同時(shí)這兩個(gè)目錄都是點(diǎn)打頭的,那么一般情況下就是隱藏文件,同時(shí)通過(guò) .gitignore 文件也可以看到,對(duì)于 flutter module 形式來(lái)說(shuō),這兩個(gè)文件夾都是被忽略的,畢竟 flutter module 的核心,還是為了方便以 module 的形式集成到原生的項(xiàng)目中,內(nèi)部的兩個(gè)原生目錄,一方面是為了方便集成,另一方面是便于直接運(yùn)行執(zhí)行 hot-reload 的調(diào)試。
以上就是Android原生項(xiàng)目集成Flutter解決方案的詳細(xì)內(nèi)容,更多關(guān)于Android集成Flutter的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android實(shí)現(xiàn)定時(shí)器的五種方法實(shí)例詳解
這篇文章主要介紹了Android實(shí)現(xiàn)定時(shí)器的五種方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02
Android自定義控件實(shí)現(xiàn)可左右滑動(dòng)的導(dǎo)航條
這篇文章主要介紹了Android自定義控件實(shí)現(xiàn)可左右滑動(dòng)的導(dǎo)航條,能響應(yīng)快速滑動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Android編程實(shí)現(xiàn)調(diào)用相冊(cè)、相機(jī)及拍照后直接裁剪的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)調(diào)用相冊(cè)、相機(jī)及拍照后直接裁剪的方法,涉及Android拍照及圖形處理相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
Android創(chuàng)建文件實(shí)現(xiàn)對(duì)文件監(jiān)聽(tīng)示例
Android創(chuàng)建文件實(shí)現(xiàn)對(duì)文件監(jiān)聽(tīng),可以用android.os.FileObserver;類(lèi)來(lái)實(shí)現(xiàn),下面是實(shí)現(xiàn)代碼,內(nèi)有注釋2014-01-01
Android程序開(kāi)發(fā)之自定義設(shè)置TabHost,TabWidget樣式
這篇文章主要介紹了Android程序開(kāi)發(fā)之自定義設(shè)置TabHost,TabWidget樣式的相關(guān)資料,需要的朋友可以參考下2016-03-03
android控件實(shí)現(xiàn)單擊拖動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了android控件實(shí)現(xiàn)單擊拖動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
MVVMLight項(xiàng)目Model?View結(jié)構(gòu)及全局視圖模型注入器
這篇文章主要為大家介紹了MVVMLight項(xiàng)目中Model及View的結(jié)構(gòu)及全局視圖模型注入器的使用說(shuō)明,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01
超實(shí)用的android自定義log日志輸出工具類(lèi)
這篇文章主要為大家詳細(xì)介紹了一個(gè)超實(shí)用的android自定義log日志輸出工具類(lèi),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01

