Flavor在多子module的项目环境下,依赖冲突的处理

        最近加入了新公司,需要对已有项目改造使用Flavor实现多渠道打包。

        项目是经典的多module依赖关系,最底层是common与网络,上层是app,中间是各种业务模块。

        在使用flavor时遇到一个问题,因为除了多渠道之外,我还想把网络层也抽取出来,毕竟官方也是支持这种操作的嘛,flavorDimensions后面可以配置多个维度,比如我既需要多渠道,又需要多环境切换,那么就可以配置成:

android {
    defaultConfig {
        flavorDimensions "channel","environment"

       }

productFlavors {
    dev {
        dimension "environment"
        buildConfigField "String", "API_HOST", '"http://xxxxx/"'
    }
    prod {
        dimension "environment"
        buildConfigField "String", "API_HOST", '"http://xxxxx/"'
    }
    normal {
        dimension "channel"
        resValue "string", "app_name", "测试桌面"
    }
    szxcskj {
        dimension "channel"
        applicationIdSuffix ".szxcskj"
        resValue "string", "app_name", "电视之家"
    }
}
}

两个维度,一个表示渠道,一个表示网络环境,可以有dev,test,uat,prod等。

        随后发现网络层是需要network模块下的,而只给network配置,不给其他模块配置环境,又会报错:

Cannot choose between the following variants of project :module_net:
- devDebugApiElements
- prodDebugApiElements

        类似这样的错误,因为network配置了两个Flavor,而其他业务模块需要依赖网络层,但却不知道应该使用哪个flavor,所以报错。

        虽然知道这个问题只需要把所有依赖的业务模块全部配置上对应的flavor就能解决,但是我们的业务模块有很多,而且我担心不便于后期维护,所以还是想找找其他方法。

        在搜了很多资料,与chatGPT多轮对话,我是这样解决的。

先要学习两个东西:matchingFallbacks和missingDimensionStrategy。

我们假设A为主模块,B为副模块,A依赖B。

matchingFallbacks

适用场景:适合主模块想要以自己的某个flavor去匹配副模块的一个或多个flavor时。

场景:主副模块dimension相同,但主模块只有一个dev环境配置,而子模块有两个,需要主模块进行一个二选一。

A:flavor
dev
B:flavor
dev1
dev2

需要在A模块做以下配置:

flavorDimensions "env"
productFlavors{
    dev{
        dimension "env"
        matchingFallbacks = ['dev1', 'dev2']
    }
}

在dev中配置matchingFallbacks,表示如果在子模块中找不到当前Flavor(dev Flavor),则会去寻找子模块的dev1与dev2,优先匹配dev1。

missingDimensionStrategy

适用场景:主模块不想配置自己的flavor或者不想配置和子模块一样的dimension,或并不关心子模块使用哪个flavor。可以让子模块遇到该情况时,自动根据配置的优先顺序选择使用子模块flavor。

场景:主模块没有配置环境dimension,并不关心使用哪个环境,需要帮他指定一个优先级进行选择。

A:flavor

B:flavor
dev
test

需要在A模块做以下配置:

defaultConfig{
    missingDimensionStrategy "env","dev","test"
}

在defaultConfig中配置missingDimensionStrategy,第一个参数是dimension,后续为优先级,如果子模块有dev和test,那么优先使用dev;如果子模块只有test,那么就使用test。

另一个案例:

场景:主模块配置了多个包,每个包使用的sdk版本不同,需要指定每个包使用哪个sdk版本。

    productFlavors {
        kukan {
            dimension "channel"
            resValue "string", "app_name", "酷看视频(sdk 1.0)"
            buildConfigField "String", "KK_AD_APP_KEY", '"ebfff335250d4912b0118b0eb1ea5e02"'
            missingDimensionStrategy "version", "standard"
        }
        youku {
            dimension "channel"
            applicationId "com.kukan.youku.demo"
            resValue "string", "app_name", "优酷(sdk 3.0)"
            buildConfigField "String", "KK_AD_APP_KEY", '"e90abd900c1a40139464af11fea7bfa0"'
            missingDimensionStrategy "version", "high"
        }
        aqy {
            dimension "channel"
            applicationId "com.kukan.aqy.demo"
            resValue "string", "app_name", "爱奇艺(sdk 3.0)"
            buildConfigField "String", "KK_AD_APP_KEY", '"daa07b98b24547c0bf5830c8b9ba3f64"'
            missingDimensionStrategy "version", "high"
        }
        txtv {
            dimension "channel"
            applicationId "com.kukan.txtv.demo"
            resValue "string", "app_name", "腾讯视频(sdk 2.0)"
            buildConfigField "String", "KK_AD_APP_KEY", '"4b31eefa15474d9a80c383dc88ba4127"'
            missingDimensionStrategy "version", "low"
        }
    }

多个包需要使用不同的子模块的sdk版本,子模块做如下配置:

    productFlavors {
        standard {
            dimension "version"
            versionCode Integer.valueOf(VERSION_CODE)
            versionName VERSION_NAME
            buildConfigField "String", "VERSION_NAME", VERSION_NAME
            buildConfigField "Integer", "VERSION_CODE", VERSION_CODE
        }
        low {
            dimension "version"
            versionName "2.0"
            versionCode Integer.valueOf("2")
            buildConfigField "String", "VERSION_NAME", '"2.0"'
            buildConfigField "Integer", "VERSION_CODE", "2"
        }
        high {
            dimension "version"
            versionName "3.0"
            versionCode Integer.valueOf("3")
            buildConfigField "String", "VERSION_NAME", '"3.0"'
            buildConfigField "Integer", "VERSION_CODE", "3"
        }
    }

参考资料:配置 build 变体  |  Android 开发者  |  Android Developers

总结:主模块和副模块flavor不相同或数量不同时,如何处理?

处理思路:

当主副模块的dimension相同时,应尽量使用matchingFallbacks方案,让自己的一个flavor去支持副模块的一个或多个flavor。

如果主副模块dimension不同,或主模块不关心子模块的flavor时,应使用missingDimensionStrategy的方案,可以忽视子模块的某个dimension下的flavor,并且为其设置优先级。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值