java生成多个控件_一个快速生成R2.java中fields的插件

介绍

在子 module 中使用 ButterKnife 时,如果想使用 ButterKnife 提供的编译期注解,那么就得使用 ButterKnife 的 gradle 插件所生成的R2.java,比如 @BindView( R2.id.xxx ),关于更多 R.java 与 R2.java 的资料可以看我这篇文章 R.java、R2.java是时候懂了。

当我们在子 module 中新增资源 id 时使用 R2.id.xxx 会报红,报红的原因是 R2.java 是依赖 R.java 生成的,必须重新 build project 生成全新的 R2.java,但这样耗时太久了,大点的工程基本需要四五分钟,报红又使强迫症实在看不下去,那么 R2Assistant 就是来解决这个问题的,使用这个插件可以快速生成 R2.java 中还不存在的 fileds,从而提高工作效率。

演示

14dd9814a5b9?from=timeline&isappinstalled=0

r2assistant.gif

使用

在主工程的 build.gradle 中添加插件

apply plugin: 'me.wangyuwei.r2assistant'

buildscript {

repositories {

maven {

url 'https://dl.bintray.com/wangyuwei/maven'

}

}

dependencies {

classpath 'me.wangyuwei:r2assistant-plugin:1.0.0'

}

}

运行命令

如果你想对所有的子 module 生效,执行 ./gradlew sweepR2

如果你只想对指定的子 module 生效,执行 ./gradlew sweepR2 -PmoduleName=${subModuleName}

原理

原理其实很简单,基本利用正则表达式。

1、写出 @BindView( R2.id.xxx ) 的正则 R2\.id\.([\w]*

2、遍历 /src/main/java 下的所有 java 文件,并找出所有匹配 1 中正则的资源名:

File srcDir = new File(subProject.projectDir.path.toString() + "/src/main/java")

srcDir.eachFileRecurse(FileType.FILES) { File file ->

if (file.toString().endsWith(".java")) {

String fileContent = new String(file.bytes)

Pattern p = Pattern.compile(FIELD_SRC_ID_REGEX)

Matcher m = p.matcher(fileContent)

while (m.find()) {

srcFieldsSet.add(m.group(1))

}

}

}

3、写出子 module 对应的R2.java 中 id 的正则 ,如 @IdRes public static final int action_bar = 0x7f0a004f;,对应的正则是:@IdRes[\s]*public static final int ([\w]*) = *[\w]*;

4、找出子 module 对应的R2.java 中 符合 2 中正则的资源名:

File r2File = new File(subProject.buildDir.path.toString() + "/generated/source/r/debug/" + packageName.replaceAll("\\.", "/") + "/R2.java")

String r2Content = new String(r2File.bytes)

Pattern p = Pattern.compile(FIELD_R2_REGEX)

Matcher m = p.matcher(r2Content)

while (m.find()) {

r2FieldsSet.add(m.group(1))

}

5、找出 /src/main/java 下的新增资源:

srcFieldsSet.each {

if (!r2FieldsSet.contains(it)) {

R2Log.log("add filed: ${it}")

generateFieldsSet.add(it)

}

}

6、在 R2.java 中生成新的 filed ,新增 filed 的值可以随便撸,反正运行时用不着:

def STR_CLASS_ID = '''public static final class id {'''

int index = r2Content.indexOf(STR_CLASS_ID)

StringBuilder sb = new StringBuilder()

sb.append(r2Content.substring(0, index + STR_CLASS_ID.length()))

generateFieldsSet.each {

sb.append("\n\t@IdRes\n\tpublic static final int ${it} = 0x7f888888;\n")

}

sb.append(r2Content.substring(index + STR_CLASS_ID.length(), r2Content.length()))

r2File.delete()

r2File.withWriter(StandardCharsets.UTF_8.name()) { writer ->

writer.write(sb.toString())

}

7、简单吧。

尾语

实现这个功能其实有很多方案,我的这种并不是最好的,我目前想的一个不错的方案是监听 xml 里的变化,如果有新增资源 id ,而这个 id 在 R2.java 中又不存在,那么自动添加这个 field,而不用现在这样执行一个task,感兴趣的同学可以做做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值