Project address: github.com/JeasonWong/…
introduce
When using ButterKnife in a child module, if you want to use compile-time annotations provided by ButterKnife, you use r2.java, which is generated by ButterKnife’s Gradle plug-in. For example, @bindview (r2.id.xxx). For more information on R.java and R2. Java, see my article.
When we use R2.id. XXX to add resource ID in sub-module, r2. Java will be red. The reason is that R2. Java is generated by r.Java, and we have to rebuild project to generate a new R2. Java, but this takes too long. Big projects can take four or five minutes to complete, and the results can be overwhelming. R2Assistant is here to help with this problem by quickly generating fileds that don’t yet exist in R2. Java.
demo
use
Add plug-ins to build. Gradle in the main project
apply plugin: 'me.wangyuwei.r2assistant'
buildscript {
repositories {
maven {
url 'https://dl.bintray.com/wangyuwei/maven'
}
}
dependencies {
classpath 'me.wangyuwei:r2assistant-plugin:1.0.0'
}
}Copy the code
Run the command
If you want to apply to all child modules, execute./gradlew sweepR2
/gradlew sweepR2 -pmodulename =${subModuleName}
The principle of
The principle is actually very simple, the basic use of regular expressions.
1, write @bindView (r2.id.xxx) re R2\.id\.([\w]*
/ SRC /main/ Java; / SRC /main/ Java;
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)) } }}Copy the code
@idres public static final int Action_bar = 0x7F0a004f; @idres public static final int action_bar = 0x7F0a004f; , the corresponding regular is: @ IdRes [\ s] * public static final int (*) [/ w] [/ w] = * *;
Find resource names in r2. Java that match regular names in 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))
}Copy the code
/ SRC /main/ Java
srcFieldsSet.each { if (! r2FieldsSet.contains(it)) { R2Log.log("add filed: ${it}") generateFieldsSet.add(it) } }Copy the code
6, generate new filed in R2. Java, the new field value can be arbitrarily arbitrarily, anyway, run without:
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()) }Copy the code
7. Simple.
The tail language
There are many ways to implement this function, but mine is not the best one. A good solution I have in mind is to listen for changes in XML, and if there is a new resource ID that does not exist in R2. Java, add the field automatically instead of executing a task like this. If you’re interested, you can do it.