美文网首页Android零散知识Android开发Android知识
Android 利用Gradle实现差异化构建

Android 利用Gradle实现差异化构建

作者: EoniJJ | 来源:发表于2017-03-14 15:06 被阅读2068次

引言

最近项目中引用的第三方库越来越多,其中一些只在开发中才需要,在正式版本中虽然没开启,但仍被打包进了apk包中,使apk包中增加了无用的代码,本文便是为了解决此问题。

dependencies的多种方式

首先我们先来回顾一下在gradle中的多种dependencies方式。

  • Compile 默认的依赖方式,任何情况下都会依赖。
  • Provided 只提供编译时依赖,打包时不会添加进去。
  • Apk 只在打包Apk包时依赖,这个应该是比较少用到的。
  • TestCompile 只在测试时依赖
  • DebugCompile 只在Debug构建时依赖
  • ReleaseCompile 只在Release构建时依赖

实现差异化构建

这里我们以facebook的stetho为例子,现假如我们只需要在开发的时候使用stetho,而在正式上线时不使用,我们可以这样写


通常我们会在Application中进行初始化Sdk的操作

public class TestApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {
            Stetho.initializeWithDefaults(this);
        }
    }
}

这样写在我们将依赖方式改成debugCompile后会发现正式打包release的时候会编译失败,因为正式打包时并不会将debugCompile的内容打包进去,而Application中又包含了相关的代码,所以便会提示找不到xx类。

这里我们在src目录下建立debug目录和release目录,并在这两个目录下面建立一个SdkManager类。


这里要注意debug和release的包结构需要相同,且不能在main目录下仍有相同的类。

SdkManager的代码很简单,debug中的SdkManager如下:

public class SdkManager {
    public static void init(Context context) {
        Stetho.initializeWithDefaults(context);
    }
}

因为我们release中不需要进行依赖,故release中的SdkManager便没作其他操作,大家也可以根据实际需求,如有什么是需要仅在release下使用的,便可以在这里进行操作。release中的SdkManager如下:

public class SdkManager {
    public static void init(Context context) {

    }
}

然后在Application中我们只需这样调用

public class TestApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        SdkManager.init(this);
    }
}

这样我们便完成了简单的差异化构建,考虑到在项目中我们很可能很多个moudule,在module中又要实现差异化构建,这里我们也新建一个名为testlibrary的module实践一下

主工程的build.gradle

这里我们在主工程中对moudule进行依赖,并且在module中采用debugCompile方式依赖第三方的库

module的build.gradle

然后编译,会发现直接提示错误


这是因为主工程依赖子module时默认依赖的是子module的release版本,而我们的第三方库仅在debug下进行依赖,即debug版本的主工程依赖的是release版本的module,所以肯定会编译失败,提示找不到xx类。那么我们只需要让主工程在debug版本下依赖module的debug版本,在release下依赖module的release版本即可解决问题。

首先在module的build.gradle文件中,增加 publishNonDefault true ,让module不再按默认只构建release版本

android {
     ...
    publishNonDefault true
}
dependencies {
    ...
    debugCompile 'com.facebook.stetho:stetho:1.4.2'
}

在主工程的build.gradle中,增加如下代码:

dependencies {
     ...
    debugCompile project(path:':testlibrary',configuration:'debug')
    releaseCompile project(path:':testlibrary',configuration:'release')
}

重新编译,即可编译通过。这里我们只是举了简单的例子,实际开发中大家可能会有各种各样的productFlavors,在不同的productFlavors中依赖也可能不同,但实现差异化构建的方法都是一样的,这里就不一一展开进行说明了。

相关文章

网友评论

  • 帅帅哒哟:大神,按照你说的方式,新建了 debug 目录 和 release 目录,但是这两个目录里面类无法访问,请问怎么回事
  • 天煞魔猎手:如果library中存在多个渠道(比如alpha, beta),那么原本的写法
    debugCompile project(path:':testlibrary',configuration:'debug') 就不对了,应该怎么写好呢?
    天煞魔猎手:如果library存在多个productFlavors 的话,假设存在alpha,那么project的alpha渠道可以这样子
    ``alphaCompile project(path: ': testlibrary', configuration: 'alphaDebug')``

    参考[这里](http://stackoverflow.com/questions/24860659/multi-flavor-app-based-on-multi-flavor-library-in-android-gradle)
  • 聪聪的豆芽:请问,如果app引用model为compile,model引用stetho为debugLibrary,那么按照3的配置打release包的时候stetho还是会被打包进去,请问是这样的么?
    EoniJJ:@聪聪的豆芽 你要先创建在不同模式下的SdkManager,而不是直接调用你的那个类库。不然就会报找不到xx的错误。然后你说的compile project(path:':testLibrary',configuration:configuration)会把包打进去,是否有在不同版本下对configuration进行赋值?还有就是module有没有改为debugCompile?
    聪聪的豆芽:@EoniJJ 我现在测试的,如果按照compile project(path:':testLibrary',configuration:'release')这种配置打release包的时候会提示类找不到错误,但是如果按照你文中所说的方式的话compile project(path:':testLibrary',configuration:configuration)打release包的时候就会把stetho打包进去,你可以按照文中方式然后打包的时候看会不会出现类找不到的错误。
    EoniJJ:@聪聪的豆芽 不会打包进去,compile方式依赖module默认依赖该module的release版本
  • v丶L:请问一下·我一个项目有10个以上的渠道,我在每个渠道里面都定义几十个buildConfigField,这样导致我的gradle文件的代码太多,请问有什么方法可以每个渠道一个gradle文件?
    v丶L:@EoniJJ 请问怎么引入?
    EoniJJ:@Abtswiath丶 分渠道写多个gradle文件,把你的buildConfigField定义写到对应的gradle文件里面,然后统一进行引入就可以了。评论没法上图片,不明白的话再联系我~
    v丶L:http://www.abtswiath.com/Public/Uploads/test.png
    就是像这样的
  • 飞天德先生:亲,写的不错哦~~给个赞
    EoniJJ:@飞天小花猫 谢谢支持~

本文标题:Android 利用Gradle实现差异化构建

本文链接:https://www.haomeiwen.com/subject/wqwcnttx.html