Gradle排除依賴模組的某個類

weixin_33766168發表於2019-02-15

好久沒寫文章了,開工第一天來一發開門紅。既然沒什麼可寫的,就簡單聊聊Gradlew吧,是Gradle,命令敲多了習慣加個w,開個小玩笑。gradle用來構建專案可謂是十分的靈活,剛開始接觸也許覺得有點懵,覺得這個東西就是多餘的,但是用多了就真的會愛上它。
我之前做元件化的時候就碰到鍋這樣一個問題,怎麼排除某個類

Gradle怎麼排除所依賴的模組的某各類

其實我覺得在很多的情況下都會碰到這個問題,比如你的老大寫了個BaseModule,裡面有很多東西,你就沒必要造輪子了,但是其實你這個專案中用不到這麼多,那就沒必要在打包的時候也把多餘的程式碼打進去,但是你又不能刪掉,因為很多個模組都依賴這個Base模組,所以你只能用“排除”的方法來去掉多餘的程式碼。再比如你自己的模組和所依賴的模組有同名類,包名都相同的那種,那就肯定編譯不過,所以你要排除相同類。甚至還有很多情況需要你在依賴中排除某個類或者某個包。
那麼該怎麼做?
只要稍微用過gradle構建專案的都知道,如果我們在依賴時出現了相同的jar包,我們是可以排除的

implementation fileTree(include: ['*.jar'], dir: '../balabala/balabala', exclude: ['重複包1.jar', '重複包2.jar'])

這樣確實能排除某個jar包來達到解決jar包重複的問題,但是用這種方法你能排除到某個類嗎?不能。
比如一般新手寫依賴module都會這樣寫

 implementation project(':testModule')

然後你想排除這個模組中的Test.java 這個檔案,你能這樣寫嗎?

 implementation project(':testModule',exclude:['Test.java'])
或者
implementation project(':testModule'){
      exclude :'Test.java'
}

這樣寫肯定不行,可能閉包的寫法寫錯了,我也不太記得這個的閉包怎麼弄來著,好像是

implementation(project(':testModule')) {
    exclude group: 'com.xxx.xxx.Test.java', module: 'testModule'
}

還是這個來著

implementation(project(':testModule'){
    exclude group: 'com.xxx.xxx.Test.java', module: 'testModule'
})

但是這樣的做法能排除掉掉這個Test.java嗎?我試過是不行的,如果有朋友能用這種方法排除單個檔案請告訴我。
既然這種方法沒辦法排除類,那麼要怎麼做?

方案一:放棄implementation project,使用sourceSets

sourceSets是java外掛的東西,他能把程式碼檔案匯入到相應的地方,無論是絕對路徑還是相對路徑,我之前有寫過一篇sourceSets的文章,獲取網上也能找到很多關於sourceSets的文章,你把目標Module的java、res、lib等引進來,即使不使用implementation project的方法,也能讓這個module能夠獲取到目標module的東西。而且使用sourceSets的話可以很方便的exclude某個檔案。
但是我覺得這樣的方法不應該叫做“依賴”,更應該叫做“引用”或者“匯入”。
所以這種方法更像是一種對檔案的操作,copy的感覺,所以這種方法也就有了不足的地方,假如你在某種情況下需要引用ModuleA,某種情況下引用ModuleB,要麼你就加個判斷,要麼就每次都改程式碼,要是有兩個還好說,要是有20幾個Module呢?我們總不能這樣玩吧,就算是能,當你每次在gradle中看到這段程式碼時,相信你也會老闊疼。

方案二:在目標模組就進行排除程式碼

什麼意思呢?比如說你想要依賴ModuleA,但是又想排除某些檔案,我們可以直接在ModuleA中進行排除,意思是你依賴的ModuleA就已經少了你想排除的程式碼。
這樣做的話可以讓依賴的那一方不用考慮特殊情況,雖然像上面說的情況多的時候也要寫挺多程式碼,但是這些邏輯會很清晰,很容易管理,我個人更傾向於使用這樣的方法也排除單個檔案。哪怕最上面說的implementation project時exclude能夠實現,我依舊更傾向於在某塊本身進行排除。
但是我們要怎樣控制呢,難道每次都要去修改多個gradle檔案嗎?其實在gradle中我們可以使用全域性變數。

1.建立一個config.gradle寫變數
// 配置全域性變數
ext{
    configOne = [isRealy:true]
}

假設我這樣有一種情況,叫configOne ,這種情況下isRealy這個值是true,這種情況下我們要在引用模組時排除掉某個類。

2.在全域性gradle中引用config.gradle
apply from: 'config.gradle'
......
3.在目標gradle中加入構建邏輯

假如我的目標模組 Moudle->myone中有兩個類OneLog、TwoLog,然後我想在A模組依賴時這兩個類都有,在B模組依賴時沒有TwoLog。
在myone的gradle寫

def configOne = rootProject.ext.configOne
android {
    .....

     sourceSets{
        main{
            java{
                if(configOne.isRealy) {
                    exclude 'com/example/kylin/myone/TwoLog.java'
                }
            }
        }
    }

}

然後我們在A模組引用時,把isRealy改成false,在B模組引用時把isRealy改成true這樣就行了。

相關文章