秦子帅明确目标,每天进步一点点.....

作者 |  小码哥哥地址 | juejin.im/post/5e1ef261f265da3e0535f10a

介绍日常开发过程中除了主工程代码,肯定也少不了调试代码,如日志、调试开关、调试工具、功能Mock等等,此时就需要一个开发阶段使用的开发环境。现在很多项目都使用云测试,三方云测试平台(如testin, 阿里云等等)测试时往往无法跳过登录,所以要在云测的安装包中内置登录token,还要指定云测接口等等一些云测场景下的一些特殊功能,此时就需要一个专为三方云测平台使用的云测环境。项目上线当然需要有线上环境 此外AS/Gradle还内置了debug环境和release环境。那么多不同的环境,代码如何去做管理? 又如何把不同环境的代码完全隔离开来?我们必须要保证调试、Mock等等这些业务无关的代码完全不能影响到线上。首先, 我们使用AS新建一个项目, 我们看看AS/Gradle有什么?如上图所示, AS已经在src目录下创建三个SourceSet目录,分别是androidTest, main和test,其中main是主工程目录,其他两个是用于单元测试目录。AS/Gradle只有这三个SourceSet目录吗?当然不是!我们知道build.gradle配置文件中,可以配置buildTypes.默认已经有debug和release两个buildType. 我们还可以自定义一个buildType名字叫custom.

android {    ...        buildTypes {        debug {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }        release {            minifyEnabled true            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }        custom {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }    }}

执行同步操作后,我们点开AS左侧的"build Variants",我们可以选择具体使用哪个buildType很多人可能会问, 这有什么用?这真的很有用!上面说过AS已经在src目录下创建了名为"main"的SourceSet目录和另外两个test目录。此时我们可以在src目录下再创建一个debug/release/custom目录,目录下的内容和main目录下内容一致。main目录一直处于激活状态,但同一时刻只会有一个buildType的SourceSet目录会被激活,如下图所示。编译时,Gradle会自动合并多个SourceSet目录。AS/Gradle还支持根据buildType引入其他module或者三方仓库

dependencies {        ...        debugImplementation project(":debugLib1")        debugApi 'com.android.support:appcompat-v7:28.0.0'                customImplementation project(":customLib")        customApi 'com.google.code.gson:gson:2.8.5'        ...    }

除了buildType,AS/Gradle还支持productFlavors,内容和buildTypes类似,可自行百度这里不再赘述。需要强调的是Gradle在编译时可以同时有一个buildType,一个productFlavor和main三个SourceSet共存,编译过程中会自动合并三个SourceSet目录.现在,如何使用多环境已经显而易见了,我们只要按需自定义buildType/productFlavor,然后将调试或者Mock的代码放到对应的buildType/productFlavor的SourceSet下就可以做到不同环境代码分离了。代码分离就一切顺利了吗?实际操作过程中会发现,buildType/productFlavor是可以直接引用到main下面的代码,相反却是不可以的,因为一旦做buildType/productFlavor切换操作的时候,main就可能找不到buildType/productFlavor中的类了。问题来了,既然main无法直接引用buildType/productFlavor中的代码,那么buildType/productFlavor中的代码如何初始化?main又如何调用这些类呢?就以上面说的云测环境做例子,假设我为云测创建了一个productFlavor名字叫cloud,我想要在云测环境app执行初始化的时候调用一次登录接口,这样就可以内置token而不需要在云测环境手动登录了,

public class LoginManager {    public static void login() {        //do login    }}

如何触发这个登录操作是一个问题。通常我们会在自定义Application的onCreate()方法中执行初始化。

public class App extends Application {        @Override    public void onCreate() {        LoginManager.login(); //这里不应该直接引用LoginManager, 因为LoginManager在productFlavor为cloud的SourceSet中, 一旦切到其他productFlavor,LoginManager类就找不到了    }}

这里有一个办法 在cloud中新建一个CloudApp继承自main中的App,然后在could的AndroidManifest中引用

        android:name="chao.app.cloud.CloudApp"         tools:replace="android:name" //必要, 使用CloudApp替换App        ...        />
public class CloudApp extends App {    @Override    public void onCreate() {        super.onCreate();        LoginManager.login(); //这样就不用担心buildType/productFlavor切换导致类找不到的问题了    }}

简单的场景里这个方法是很有效的,场景再复杂一点呢如果BuildVariants选择cloudDebug,即productFlavor是cloud,buildType是debug,debug也需要有自己的初始化,但是AndroidManifest中Application最终只能有一个。所以稍微复杂点的场景问题会变得很棘手。另外由于存在多环境切换,buildType/productFlavor中的类是不能直接被调用的。
如何解决
ServicePool是一个用于组件化通信的神器。可以很有效的解决上述问题。https://juejin.im/post/5e1e76c6518825267f699a3d使用ServicePool初始化Service初始化代替Application初始化,cloud中定义一个CloudInit,debug中定义一个DebugInit.

public class App extends Application {    @Override    public void onCreate() {        super.onCreate();        AndroidServicePool.init(this); //初始化ServicePool    }}
@Init(lazy = false) //ServicePool默认所有组件使用懒加载,这里取消掉懒加载模式,让ServicePool初始化后理解加载这个Service@Servicepublic class CloudInit implements IInitService {    @Override    public void onInit() {        LoginManager.login();    }}
@Init(lazy = false) //ServicePool默认所有组件使用懒加载,这里取消掉懒加载模式,让ServicePool初始化后理解加载这个Service@Servicepublic class DebugInit implements IInitService {        @Override    public void onInit() {        //do something    }}

上面已解决了多环境初始化问题,那么如何解决buildType/productFlavor下类又是如何被调用的呢?相信看完ServicePool你一定能找到答案。本文档涉及demo代码:https://github.com/luqinx/Documents

---END---

 创作不易,点个“在看

android debug bridge tools_如何优雅的管理多环境下的Android代码相关推荐

  1. android debug bridge tools_飞凌干货丨Android 应用程序如何获取system权限

    当Android应用程序用到重启系统.关闭系统.修改系统时间等功能时,需要用到system权限. 本文以OKxx18平台实现重启功能的应用程序PermissionTest为例,说明获取系统权限的方法. ...

  2. Android开发工具——ADB(Android Debug Bridge) 一概览

    Android Debug Bridge (adb) 是一个android开发人员必会的多功能的调试工具,确实它的名字一样,它在开发者和目标机器之间,架起了一座bridge. adb的用法很简单,只要 ...

  3. [ADB]ADB(Android Debug Bridge)简介及基础(不包含命令)

    "Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an ...

  4. adb(Android debug bridge)命令

    From:https://www.cnblogs.com/huanyou/p/5133737.html ADB 用法大全: github 地址:https://github.com/mzlogin/a ...

  5. Android Debug Bridge(ADB)学习总结

    Android Debug Bridge Android调试桥(ADB)是一种多用途的命令行工具.通过它我们可以和模拟器或者设备通信.ADB是一个客户端-服务器程序,包括三个组成部分: 客户端(Cli ...

  6. ABD — android debug bridge 简略介绍

    ABD - android debug bridge 简略介绍 文章目录 ABD - android debug bridge 简略介绍 一.adb是什么? 二.组成部分 三.adb 常用命令 四.总 ...

  7. Android Debug Bridge(adb)

    Adb google官方文档翻译,源文档地址如下 https://developer.android.google.cn/studio/command-line/adb Android Debug B ...

  8. Android开发者指南(1) —— Android Debug Bridge(adb)

    Android Debug Bridge Android调试桥接器,简称adb,是用于管理模拟器或真机状态的万能工具,采用了客户端-服务器模型,包括三个部分: * 客户端部分,运行在开发用的电脑上,可 ...

  9. Android Debug Bridge 技术实现原理

    Android Debug Bridge 技术实现原理 ADB(Android Debug Bridge)技术实现 =============== I.总览 =============== ADB用来 ...

最新文章

  1. 区块链技术之Fabric逻辑架构详解
  2. 创建一个纯色的背景图
  3. 23 | MySQL是怎么保证数据不丢的?
  4. Centos7换yum源
  5. springsecurity 认证之密码模式
  6. 谁将成为下一个风口?
  7. python怎么定义全局变量_python中如何定义全局变量
  8. 精妙的SQL和SQL SERVER 与ACCESS、EXCEL的数据导入导出转换
  9. 几款ReactJS最优秀的UI框架
  10. S.O. 推出程序员身价计算器,看看自己值多少钱?
  11. 实验一高频小信号调谐放大器
  12. 获得代理ippython_Python3.x:免费代理ip的批量获取并入库
  13. Boost Asio介绍
  14. Neural Collaborative Filtering
  15. ShareTechnote系列LTE(10):多小区多RAT之间的交互
  16. 6.Striped64源码解析
  17. 解决mac登录APPLE ID无限重复弹窗提示登录
  18. 结构化数据和非结构化数据的提取【Python篇】
  19. 神奇的sqrt函数以及高精度记时函数
  20. 阿里云王牌架构师二问开发者:容器和虚拟化你会怎么选?

热门文章

  1. SpringBoot-@Configuration
  2. Spring5的Web 组件
  3. SpringMVC的请求-文件上传-单文件上传的代码实现1
  4. springboot 日志设计结构
  5. 构建eureka高可用服务
  6. Spring Security OAuth2源码解析(二)
  7. MySQL出现慢日志超过2秒_MySQL慢日志功能分析及优化增强
  8. python3怎么使用qstring_请问PyQt的QString和python的string的区别?
  9. 验证哥德巴赫猜想:任何一个大于6的偶数均可表示为2个素数之和
  10. 一家创业公司发展历程-真实记录