android 一套程式碼多用 以及 多套程式碼用於一個專案

超威藍貓發表於2019-03-04

文章關鍵字 productFlavors

目前在專案中遇到了這樣一種情況,公司的產品需要在不同的機子(自己產品)上進行執行,有的是正常手機 有的是沒有螢幕的手機,需要另外做處理。那麼現在問題來了,總不可能一個產品一個專案把,那麼我們就可以通過productflavors進行程式碼多用

專案使用mvp架構 demo也是以此為前提

第一種情況,程式碼不變,素材變化

舉一個極端的例子,你家的app賣不出,別人來代理你家的app,說圖示要換成他家的,那麼你怎麼辦?總不可能直接拿專案改把,萬一又說不要你家app了呢?(開個玩笑)

步驟:
先將android studio的目錄結構改成project

image.png

在與main同級下新建一個目錄
我這裡叫seller

image.png

並且根據main目錄的目錄結構(一定要一樣),新建res 新建values 新建strings.xml

image.png

並將原來的appname 在後面加上111

tips1:這裡說明一下,在res目錄下的替換都是批量替換,在main目錄的strings.xml裡面肯定不止一個strings,我們在seller的strings.xml下新建一個appname 並更改了值 那麼只有這個appname會被替換 其他的還是原封不動的使用main的東西
tips2:其他同理,只要是在res目錄下,都是批量替換(名字一定要一樣 無論是string 還是圖片)

在替換之前 我們還需要做一些事情,就是宣告
在gradle檔案裡面

image.png

新增一個productFlavors 裡面宣告一個seller

 productFlavors {
        seller {
        }
    }
複製程式碼

gradle sync之後
在build Variants裡面就可以看到不同的專案了

image.png
image.png

你可能會說 現在不就只剩一個了麼,想用原來的程式碼不想用seller怎麼辦?
笑哭.jpg 新增一個就好

image.png

新增一個空的origin

image.png

宣告一下

image.png

打包的時候你可以同時打兩個包

image.png
image.png

在build Variants裡面的選項的作用:你選擇哪個,執行的時候(debug run)就執行哪個版本
以上就是素材的替換

第二種情況程式碼的替換

可能某一個部分的機器需要另外的新增的程式碼 而且與原來的程式碼區別還是蠻大的
那麼我們可以進行程式碼的替換

tips1:程式碼的替換並不是部分替換 而是檔案的替換(例如一個mainActivity的替換,而不是mainActivity的某個程式碼片段的替換)

tips2:要替換的程式碼的那個檔案不能存在於main資料夾內

現在 我們在seller下新建一樣的程式碼結構

image.png

並把MainActivity檔案複製過來

image.png

並將Build Variant設定成sellerdebug

image.png

你會發現報錯 所以說替換程式碼的時候main 資料夾內不能存在那個檔案

現在將origin也複製一遍程式碼結構 並且將main資料夾內的刪除

image.png

不再報錯

Tips:目前Build Variant是sellerdebug 所以seller下面的資料夾和main資料夾是有顏色的 但是origin沒有,側面說明android studio還是挺智慧的

以上就是程式碼的替換 只要你你執行那個分支你就會執行哪裡的程式碼(沒有替換的程式碼會用main資料夾的)

一些使用心得:如果只是小部分程式碼需要替換 最後還是在main裡面if else修改 比較方便 不然你就要維護兩套程式碼 使用mvp分層的話 可以儘量減少檔案的替換 維護更少的程式碼!!!

第一二種情況可以混用

字串的替換

如果你在seller中使用一個ip origin使用一個ip 怎麼辦

productFlavors {
        seller {
            buildConfigField("String", "URL", `"www.baidu.com"`)
        }
        origin{
            buildConfigField("String", "URL", `"www.google.com"`)
        }
    }
複製程式碼

使用buildConfig欄位

String ip = BuildConfig.URL;
複製程式碼

這樣這個ip在seller下是baidu 在origin下是google 是自動的

此外 也可以在debugrelease下使用

buildTypes {
        debug{
            minifyEnabled false
            proguardFiles getDefaultProguardFile(`proguard-android.txt`), `proguard-rules.pro`
            buildConfigField("String", "URL", `"www.baidu.com"`)
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile(`proguard-android.txt`), `proguard-rules.pro`
            buildConfigField("String", "URL", `"www.google.com"`)
        }
    }
複製程式碼

專案的判斷

if (BuildConfig.FLAVOR.equals("seller")) {
            //// TODO: 2017/12/7  
        }
複製程式碼

使用flavor欄位可以判斷執行的是哪個分支 然後進行小範圍的程式碼的if else

專案的compile

例如 seller下使用騰訊的sdk
但是origin的使用百度的sdk
難道打包就需要打包兩個sdk???

image.png

舉個例子
使用分支的名字加上Compile就可以只在seller專案中compile這個東東

但是這樣有個問題 如果你在同一套程式碼裡面做了if else判斷 如果在某個分支裡面沒有compile這個包 那麼可能會報錯

//舉個例子:demo例子
//如果在seller專案中沒有compile tx的sdk 那麼編譯的時候會報錯 說沒有找到tx sdk這個類
if(flag){
  TXSdk.init(this)
}else{
  BaiduSdk,init(this)
}
複製程式碼

ui一樣的情況下 新增程式碼邏輯

在我的專案中 有一臺手機是沒有螢幕的 但是有一個lcd屏 所以我需要新增邏輯 進行處理
假設這個沒有螢幕的手機是seller專案

seller專案需要compile一個jar包這個jar包很大
因為我是sellerCompile的 在origin中是沒有的 所以我不能在main的程式碼中寫入關於這個jar的程式碼 不然origin就編譯不起來

那麼我是怎麼辦的呢?

image.png

我新增一個receiver 和一個service
通過發intent的方式 如果是seller專案自然可以收到intent 並且使用jar包的類進行處理(使用jar包的程式碼在seller分支裡面 而不是在main裡面) 就沒有問題,如果是origin專案 不會有receiver會收到這個intent 然後就不會處理

所以我是通過receiver進行中轉處理的

以上就是我在專案中遇到的一些問題 以及productFlavor的一些使用 當然 productFlavor還有其他的一些用法 大家可以自己去了解一下

專案的demo(只有結構哈):https://github.com/Lemniscate317/ProductFlavorsDemo

相關文章