Android開(kāi)發(fā)升級(jí)AGP7.0后的一些適配方法技巧
升級(jí)
年初了,我們打算升級(jí)下apg,這樣之后就擁抱下jetpack compose了??!
想用comopse有兩個(gè)必選項(xiàng)agp7.0和kotlin版本1.5.31.
Java11配置
因?yàn)閍pg7.0需要把所有的module編譯環(huán)境切換到j(luò)ava11版本上,然而這個(gè)地方很容易出錯(cuò)。
首先是命令行的配置,對(duì)于mac用戶(hù)來(lái)說(shuō),可能會(huì)寫(xiě)死默認(rèn)的java環(huán)境到1.8. 這個(gè)時(shí)候我們需要做的就是刪除bashprofile內(nèi)的java配置。
同時(shí)最好用命令行java --version嘗試下輸出的版本是不是java11。
as的配置則相對(duì)來(lái)說(shuō)比較簡(jiǎn)單了。
按照這兩個(gè)配置完成之后重新同步下工程應(yīng)該就行了。
AndroidComponentsExtension
之前在現(xiàn)在準(zhǔn)備好告別Transform了嗎?的文章就簡(jiǎn)單展開(kāi)了下AndroidComponentsExtension,新版本更換了extensions。這次給項(xiàng)目升級(jí)適配之前寫(xiě)的哪些插件,想了想用新不用久嗎,嘗試下新東西了。
onVariants
以前在寫(xiě)android插件的時(shí)候很多時(shí)候都需要在gralde的afterEvaluate方法執(zhí)行之后才能獲取到很多安卓對(duì)應(yīng)的屬性。
這次在v2的api中,則提供了非常多不同的節(jié)點(diǎn),讓我們?cè)诓煌碾A段做一些不同的事情。
比如說(shuō)onVariants,beforeVariants,finalizeDsl這三個(gè)不同的階段,正常情況下我們選擇onVariants就足夠了。
Component Artifacts
Gralde 內(nèi)的一部分核心是Task,但是要想寫(xiě)好一個(gè)Task其實(shí)并沒(méi)有想象中的那么容易。特別是一個(gè)CacheableTask,他更多的關(guān)注與他們的輸入和輸出。
構(gòu)建緩存(build cache)的工作原理是:在緩存中存儲(chǔ)已編譯的類(lèi)、測(cè)試輸出和其他構(gòu)建構(gòu)件,同時(shí)考慮所有的任務(wù)輸入,包括輸入文件內(nèi)容、相關(guān)類(lèi)路徑和任務(wù)配置。
所以在A(yíng)GP 7.0中,提供了這部分新的api讓我們簡(jiǎn)化對(duì)于task,輸入輸出這些參數(shù)的優(yōu)化,讓我們可以更專(zhuān)注到我們想要變更的東西上。
比如說(shuō)APk,MANIFEST,MAPPING_FILE,BUNDLE,AAR或者其他的一些編譯產(chǎn)物,當(dāng)前agp給我們提供的也是相對(duì)來(lái)說(shuō)比較少的一部分功能。
另外一點(diǎn)就是,我們?nèi)绻胍酪粋€(gè)task的輸入其實(shí)如果不去閱讀源碼,之后獲取對(duì)應(yīng)的路徑或者源代碼,其實(shí)是一個(gè)非常繁瑣的過(guò)程。之后還要通過(guò)變更dependon或者finalizedBy等等手段將任務(wù)插入到編譯流程內(nèi)。
所以就有了我們這次的其中一個(gè)主角Artifacts,他主要負(fù)責(zé)幫助我們將我們的task,插入到編譯流程內(nèi),讓我們盡量少的關(guān)注到輸入和輸出。
// 生成TaskProvider val taskProvider = project.tasks.register( "manifestCopy${variant.name}Task", ManifestSampleTask::class.java ) // 獲取variant的artifacts之后將Task轉(zhuǎn)化成我們所想要的 variant.artifacts.use(taskProvider).wiredWithFiles( ManifestSampleTask::mergedManifest, ManifestSampleTask::outputManifest ).toTransform(SingleArtifact.MERGED_MANIFEST)
這個(gè)就是官方的一個(gè)Artifacts的簡(jiǎn)單的使用了,通過(guò)變化我們可以輕松的完成一個(gè)有獲取合并后的Manifest作為輸入,之后以另外一個(gè)Manifest文件作為輸出的一個(gè)task。而且會(huì)被直接添加編譯流程內(nèi),就不需要我們關(guān)心他們的前置和后置任務(wù)是啥了。
registerJavaGenerateTask 沒(méi)了
原先在v1的api上吧,有registerJavaGenerateTask這個(gè)方法,能加一些簡(jiǎn)單的代碼生成的操作,比如j神以前生成的R2就是通過(guò)掛載這個(gè)方法。
這次v2版本我在A(yíng)ndroidComponentsExtension中沒(méi)找到的對(duì)應(yīng)的api,所以只能無(wú)中生友,自己搞一個(gè)出來(lái)咯。
@Override public void registerJavaGeneratingTask(@NonNull Task task, @NonNull File... sourceFolders) { getVariantData().registerJavaGeneratingTask(task, sourceFolders); } open fun registerJavaGeneratingTask( task: Task, generatedSourceFolders: Collection<File> ) { @Suppress("DEPRECATION") taskContainer.sourceGenTask.dependsOn(task) val fileTrees = extraGeneratedSourceFileTrees ?: mutableListOf<ConfigurableFileTree>().also { extraGeneratedSourceFileTrees = it } for (f in generatedSourceFolders) { val fileTree = services.fileTree(f).builtBy(task) fileTrees.add(fileTree) } addJavaSourceFoldersToModel(generatedSourceFolders) }
我仔細(xì)觀(guān)察了下registerJavaGenerateTask的源代碼,發(fā)現(xiàn)其中只做了兩件比較簡(jiǎn)單的事情。將Task掛載到generateVariantResources任務(wù)之后,然后將生成java類(lèi)的文件夾加入到sourcetSet上去,這樣就行了。
sourcetSet就是javac的將java轉(zhuǎn)化成class的編譯路徑。
所以相對(duì)來(lái)說(shuō)就比較簡(jiǎn)單,我們用新的api模擬出原來(lái)的效果就差不多可以了,我們只要找到掛載的任務(wù)之后,順便把代碼添加到j(luò)ava和kotlin的sourceset中就行了
fun Project.registerJavaGenerateTask( variant: String?, task: TaskProvider<out Task>, generatedSourceFolders: Collection<File> ) { if (variant.isNullOrEmpty().not()) { variant?.apply { // 因?yàn)閠ask生成在配置階段完成之后 afterEvaluate { findJavaGenerateTask(variant)?.dependsOn(task) } // 獲取最新版本sourceSet val application = extensions.findByType(ApplicationExtension::class.java) application?.sourceSets { findByName(variant)?.apply { generatedSourceFolders.forEach { java.srcDir(it) kotlin.srcDir(it) } } } } } }
這次升級(jí)適配主要的代碼就是這個(gè)了,其實(shí)代碼量上來(lái)說(shuō)不多。但是把有個(gè)坑點(diǎn),之前因?yàn)橥祽芯椭苯佑昧藄etSrcDirs這個(gè)api,所以文件就被覆蓋了。導(dǎo)致了一部分代碼沒(méi)有被編譯成class,導(dǎo)致了classnotfound異常。
其他
獲取applicationId,我們的插件內(nèi)有對(duì)于應(yīng)用id的判斷,之后進(jìn)行不同的manifest pleaceholder的調(diào)整。邏輯比較簡(jiǎn)單,只是切換了新版本的api而已。
if (variant is ApplicationVariant) { val applicationId = variant.applicationId.get() variant.manifestPlaceholders.put("xxxxx", applicationId) }
對(duì)resValue插入新的string或者values。也是原來(lái)就有的能力,但是要對(duì)新版本進(jìn)行一次小小的適配和更換。
private fun addAPGClassFile(config: Variant, key: String, value: String) { val resValue = ResValue(value) val reskey = config.makeResValueKey("string", key) config.resValues.put(reskey, resValue) }
啟動(dòng)configuration cache
啟用配置緩存的操作,本質(zhì)上是在項(xiàng)目的 gradle.properties 文件中設(shè)置了環(huán)境變量 org.gradle.unsafe.configuration-cache=true。
結(jié)尾
AGP對(duì)我們這個(gè)算是每年一更新了,會(huì)碰到一些新的有趣的api以及新的寫(xiě)法。另外每次新版本的AGP對(duì)于編譯上都有變更和優(yōu)化,更多關(guān)于A(yíng)GP7.0升級(jí)適配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
融會(huì)貫通Android?Jetpack?Compose中的Snackbar
這篇文章主要為大家介紹了融會(huì)貫通Android?Jetpack?Compose中的Snackbar方法及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01詳解Android內(nèi)存泄漏檢測(cè)與MAT使用
編寫(xiě)沒(méi)有內(nèi)存泄漏的程序,對(duì)提高程序穩(wěn)定性,提高用戶(hù)體驗(yàn)具有重要的意義。這篇文章主要介紹了詳解Android內(nèi)存泄漏檢測(cè)與MAT使用,有興趣的可以了解一下。2016-12-12Android動(dòng)態(tài)繪制餅狀圖的示例代碼
這篇文章主要介紹了Android動(dòng)態(tài)繪制餅狀圖的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Android編程簡(jiǎn)單設(shè)置ListView分割線(xiàn)的方法
這篇文章主要介紹了Android編程簡(jiǎn)單設(shè)置ListView分割線(xiàn)的方法,涉及Android布局簡(jiǎn)單操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02Android仿直播類(lèi)app贈(zèng)送禮物功能
這篇文章主要介紹了Android仿直播類(lèi)app贈(zèng)送禮物功能,本文通過(guò)實(shí)例代碼效果圖展示的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02設(shè)置Android系統(tǒng)永不鎖屏永不休眠的方法
在進(jìn)行Android系統(tǒng)開(kāi)發(fā)的時(shí)候,有些特定的情況需要設(shè)置系統(tǒng)永不鎖屏,永不休眠。本篇文章給大家介紹Android 永不鎖屏,開(kāi)機(jī)不鎖屏,刪除設(shè)置中休眠時(shí)間選項(xiàng),需要的朋友一起學(xué)習(xí)吧2016-03-03Android 日歷控件庫(kù),可左右滑動(dòng),顯示公歷,農(nóng)歷,節(jié)假日等功能
這篇文章主要介紹了Android 日歷控件庫(kù),可左右滑動(dòng),顯示公歷,農(nóng)歷,節(jié)假日等功能的相關(guān)資料,需要的朋友可以參考下2016-09-09kotlin中object關(guān)鍵字的三種使用場(chǎng)景
這篇文章主要給大家介紹了關(guān)于kotlin中object關(guān)鍵字的三種使用場(chǎng)景,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用kotlin具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06