自定义Android Studio gradle插件

最近打算整理一下自己的 android 开发框架,其中在整理网络请求框架的时候遇到了一点小问题,我使用的网络请求框架是现在常用的 Retrofit + RxJava + Okhttp,熟悉 Retrofit 的小伙伴都知道 Retrofit 初始化的时候需要设置 baseUrl 并且无法使用 api 修改,通常的如果我们项目中存在多个后端服务即多个 baseUrl 的时候,我们就不得不考虑怎么样才能更加优雅更加方便的使用baseUrl了,在这之前我一直使用的是创建多个 Retrofit 对象,每个对象持有一个 baseUrl ,但是不得不说这个是最差的方式了。

在网上找了找一些解决方案 解决Retrofit多BaseUrl及运行时动态改变BaseUrl?  该文章已经很好的剖析了多个 BaseUrl 以及动态改变 BaseUrl 的需求场景,并且为我们提供了很好解决方案。当然本片文章并不是复读该篇文章,而是读完这篇文章之后给了我一些启发。该作者提供的最优方案是 app 初始化时注册多个K-V,并且于 Retrofit 接口上增加 @Headers 注解,注解的值为“ConfigHost:K”,并于 Okhttp 的拦截器中解析请求的 Header,如果 Header 中存在 ConfigHost ,则根据请求头中的 K 值从初始化的 K-V 容器中获取对应的 V 值,而 V 就是我们实际上要用到的 BaseUrl,替换 @Headers 中对应的 K 或者修改 K-V 容器中的 V 值就能满足我们前面说的配置多个 BaseUrl 或者动态改变 BaseUrl 了。但是,还有没有更加优化的空间呢?如果一个 Service 中的接口数量十分多,那么每一个接口我们都去加上 @Headers 是不是显得太麻烦了,而且万一其中一个接口没加上还要可能找个半天错在哪里,作为一名程序员,能少写一点重复的代码是一点,所以,从偷懒的目的去思考,最好我们能直接把这个 @Headers 配置到 Service 上,然后每个接口就有了 @Headers 这个注解,那样是不是轻松多了,唔,我的书写习惯通常是一个 BaseUrl 对应一个 Service ,如果对 Service 进行注解就能使这个 Service 中的所有接口具备某个注解的能力,那是不是就能满足我的需求了?

一开始我想到了使用 APT 方式去修改 java 文件,然后发现或许是功力不够深厚,我只能往 apt 目录创建新文件,却没办法修改源文件为每个接口添加注解,后来只能安慰自己(修改了源文件可能并不是最好的方法啊)换个思路吧。我们知道app中的 java 文件编译后成为class文件然后 class 文件再打包到 dex 文件中,而从 java 转 class 文件的时候我们是不是能动点手脚注入我们想要的代码呢?没错了,这就是我今天要入手的目标,标题上也说了,我们是要开发一款 gradle 插件。

网上对于如何编写一个 Plugin 已经有很多例子,比如 Android组件化开发实践(九):自定义Gradle插件 大家可以看一下,我这里也不赘述,主要记录一下我的开发过程已经过程中遇到的一些问题。

首先是创建一个 module , module 名就叫 trans 吧, build.gradle 文件内容如下

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    //gradle sdk
    compile gradleApi()  
    //groovy sdk
    compile localGroovy()

    compile 'com.android.tools.build:gradle:3.4.2' 
}

group='org.linwg.dynamic'
version='1.0.0'

uploadArchives {
    repositories {
        mavenDeployer {
            //本地的Maven地址设置为D:/repos
            repository(url: uri('D:/repos'))
        }
    }
}

然后在 src/main/groovy/yourpackagename/plugin 目录下创建你的 Plugin 文件,右键 --> New File -->MyPlugin.groovy

package com.linwg.plugin


import com.android.build.gradle.AppExtension
import org.gradle.api.Plugin
import org.gradle.api.Project

class DynamicBaseUrlPlugin implements Plugin<Project> {

    void apply(Project project) {
        System.out.println("========================");
        System.out.println("hello gradle plugin!");
        System.out.println("========================");
    }
}

然后在src/main/resources/META-INF/gradle-plugins 目录下创建  org.linwg.dynamic.properties 文件,注意 .properties 前面的文件名 org.linwg.dynamic 即最终我们提供的插件名称,properties 文件内容如下:

implementation-class=org.linwg.plugin.DynamicBaseUrlPlugin

即记录了我们插件类的包名和类名。

接着根据 build 文件配置的 maven 信息,于 Android Studio 界面右侧的 gradle 目录下找到本 module 的 Tasks / upload / uploadArchives 执行上传到 maven 本地仓库的操作

接下来只要在我们的项目里面引用这个插件就可以使用了,在工程目录下的 build.gradle 文件下添加依赖:

buildscript {
    repositories {
        maven {
            //本地Maven仓库地址
            url uri('D:/repos')
        }
        google()
        jcenter()
        ...
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.4.2'
        classpath 'org.linwg.dynamic:plugins:1.0.0'
        ...
    }
}

allprojects {
    repositories {
        maven {//本地Maven仓库地址
            url uri('D:/repos')
        }
        google()
        jcenter()
        ...
    }
}

classpath 即我们 module 下配置的 groupId:moduleName:version  。

在我们的 app module build 文件下添加插件 

apply plugin: 'org.linwg.dynamic'

然后build一下,在控制台我们就能看到如下信息了

第一个插件就成功的运行起来了。

当然了,这个插件除了面向小白装逼其他屁用都没有,我们还记得我们的目的吗?是的,往 class 文件注入我们的代码,接下来是重点了。

com.android.tools:gradle 目录下为我们提供了一个类 Transform ,这个类就是方便我们对 class 文件进行字节码操作的神器,网上对它的介绍也很多,建议没了解的同志先看一遍 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值