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

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

项目地址:github.com/JeasonWong/…

介绍

在子 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,从而提高工作效率。

演示

ab7653affab982b574eb7acc55df2e04.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 中正则的资源名:

FilesrcDir=newFile(subProject.projectDir.path.toString()+"/src/main/java")

srcDir.eachFileRecurse(FileType.FILES){Filefile->

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

StringfileContent=newString(file.bytes)

Patternp=Pattern.compile(FIELD_SRC_ID_REGEX)

Matcherm=p.matcher(fileContent)

while(m.find()){

srcFieldsSet.add(m.group(1))

}

}

}

3、写出子 module 对应的R2.java 中 id 的正则 ,如@IdRes

publicstaticfinalintaction_bar=0x7f0a004f;,对应的正则是:@IdRes[\s]*publicstaticfinalint([\w]*)=*[\w]*;

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

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

Stringr2Content=newString(r2File.bytes)

Patternp=Pattern.compile(FIELD_R2_REGEX)

Matcherm=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 的值可以随便撸,反正运行时用不着:

defSTR_CLASS_ID='''public static final class id {'''

intindex=r2Content.indexOf(STR_CLASS_ID)

StringBuildersb=newStringBuilder()

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,感兴趣的同学可以做做。

来源: https://juejin.im/entry/5a2496a4f265da432e5bd51f

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值