最近我老大問我一個問題,說Android可不可以像iOS那樣,通過target對項目進行管理啊。老大提這個問題也是正常的,我公司的主要是幫別的公司做硬件定制的,每定制一個硬件就要定制一個APP,但是很多APP的定制其實都是基於同一個APP,只是改改圖標,改改部分功能,但是就是這么簡單的改變都需要新建一個項目,試想想如果有幾十個項目,剛好修復了一個bug,那么要把這個修復同步到所有項目中,那同步代碼的工作量是多么的大,而且還不能保證同步不出錯。所以老大讓我找找有沒有方法可以像iOS的target那樣處理。
這里需要先理解iOS的target是什么。知道的同學可以自行忽略這段。iOS中project包含資源、文件、信息等等,而這些就像一些積木,而target則作為標志,通過不同的標志進行組合,這里有官方的介紹,英語好的同學可以自己去看看。這樣組合的好處就是,如果一個項目只需要改變一下圖標,那只需要增加圖標的資源,然后再增加標志,那就可以生成一個新的APP。抱着試試的心態去尋找Android的target,但是Android並沒有這個東西,不過卻找到了另一個東西,那就是配置Flavor。
productFlavors
先來看一段代碼
android { compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.z.q.flavor" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } productFlavors{ flavor1{//自定義flavor1的參數 applicationId "com.z.q.flavor1" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" } flavor2{//在defaultConfig的基礎上做修改 applicationIdSuffix ".flavor2"//輸出:com.z.q.flavor.flavor2 versionNameSuffix "-flavor2"//輸出:1.0-flavor2 } } ... }
這個是module里面的build.gradle部分代碼,這里面主要增加的productFlavors,這個就是來配置不同項目的參數。在這里我配置了兩個項目,分別是flavor1和flavor2。不同的項目ID當然需要不同,配置ID的方法有兩種:
1. 第一種就是直接使用applicationId這個屬性,直接給flavor1配置一個ID;
2. 第二種就是使用applicationIdSuffix這個屬性,這個的意思是在defaultConfig的默認ID基礎上在后面追加一段。
而versionName也是和applicationId一樣有兩種方法。如果沒配置的屬性會默認的使用defaultConfig里面的屬性。到這里不同項目的build.gradle里面的配置大致完成了,如果還想了解更多的配置信息,可以到Google官網了解。
資源文件配置
在build.gradle我配置了兩個項目,那么相應的需要建立兩個資源文件夾。
在build.gradle我配置了兩個項目,那么相應的需要建立兩個資源文件夾。
這兩個文件名字必須和build.gradle里面配置的兩個Flavors名字相同,現在可以在這兩個文件夾里創建各自項目的資源了。
在這兩個文件夾里面創建資源的時候一定要和main的文件格式一致,如圖:
這個文件格式一致是指包名必須相同。這時有人可能會問為什么flavor1里面有res資源文件,為什么flavor2里面沒有呢?
我們先從main文件夾來看,在main文件夾里面有Java代碼文件,res資源文件和清單文件。在配置Flavor中,在進行構建的時候會將選中的Flavor和main進行結合構建,說白了就是如果Flavor沒有的東西就會使用main里面的代替。上圖,我就選中了flavor2,具體怎么選着請看下圖。因為flavor2中沒有res資源和清單文件,那么它就會使用main里面的res資源和清單文件;而如果選着flavor1,那么就會使用flavor1中res資源里面的布局文件。在這里可以看到不同項目中的res資源可以有相同的,Android studio在編譯的時候會優先使用Flavor里面的res資源,如果沒有再使用main的res資源。
細心的同學可能會發現Java文件夾里面的代碼文件,為什么兩個Flavor中都有Flavor代碼文件,而main中卻沒有,但是main中有MainActivity代碼文件,而兩個Flavor文件中卻沒有。這是因為在編譯的時候,Flavor的Java的文件不會覆蓋main里面的Java的文件,所以如果Flavor里面有的Java文件,main里面就不能有,如果是所有項目都相同的Java文件,那么就可以放在main文件里。
到目前為止main文件里面,已經把Java代碼文件和res資源文件說明,剩下就只有清單文件了,清單文件比較特殊,需要單獨拿來講解。
清單文件
清單文件不像Java代碼文件那樣每個項目相同的Java代碼文件不可以和main中的Java代碼文件共存,而是main和每個項目都可以有清單文件,但是又不會像res資源文件那樣項目中的res資源文件會覆蓋main的res資源文件。
在編譯的時候Android studio會把main的清單文件和選中項目的清單文件合並,但是合並就會出現沖突。其實谷歌那邊早就想到會有這些問題,所以已經提供了解決的方法了。
在這里我只介紹兩種合並方法:merge和replace
這張是main的清單文件

這是flavor1的清單文件

這是flavor2的清單文件
在main的清單文件中缺少了主題,而在flavor1清單文件中只有主題沒有其他,那么在這里使用merge就會把main和flavor1的aplication的屬性相結合。
而在flavor2中所有都齊全,只是label不同,這里使用replace就會把main里面的application的屬性全都替換掉。
如果在application中使用這兩個屬性,除了會把application的屬性和main的清單文件里面的application屬性結合以往,還會把application包含的activity,service等都結合,所有在這里要謹慎使用。
還可以使用其他屬性來進行結合,具體可以去查看Google的開發者文檔
