接下来实操写一遍,这里只使用BindView一个注解,来学习其实现过程。
第一步
新建一个Java库,取名butterknife_annotations
目录结构如下,这里只有一个注解类BindView
package com.example.butterknife_annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface BindView {
int value();
}
第二步
再新建一个Java库,取名butterknife_complier,这个库用于生成MainActivity_ViewBinding
其目录如下:
这个类就是用来查找支持的注解,并执行怎么生成代码的逻辑,不能调试代码,可以通过打印日志来查看指定位置的执行情况。这个是在编译期执行的,具体来说就是Javac来执行它,javac启动一个完整Java虚拟机来运行注解处理器,所以需要将这个类注册到Javac中。
有两种方式注册
-
需要在 butterknife_complier库的 main 目录下新建 resources 资源文件夹;
在 resources文件夹下建立 META-INF/services 目录文件夹;
在 META-INF/services 目录文件夹下创建 javax.annotation.processing.Processor 文件;
在 javax.annotation.processing.Processor 文件写入注解处理器的全称,包括包路径;
目录如图所示:
在文件中写入注解处理器的全路径:
-
第一种手动添加的方式未免有些麻烦,并且容易出错,可以借助一个库自动生成
在自定义注解处理器类的顶部加入注解:
@AutoService(Processor.class),这个注解处理器是Google开发的,可以用来生成 META-INF/services/javax.annotation.processing.Processor 文件信息。
如下图所示:
编译之后会自动生成如第一种方式添加的文件,可以在butterknife_complier/build目录下查看生成结果:
当然这里依赖要添加正确,不然可能会报错,依赖如下:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
dependencies {
implementation project(":butterknife_annotations") // 使用定义的注解
implementation 'com.google.auto:auto-common:0.10' // 这个是auto-service基础库
implementation 'com.squareup:javapoet:1.10.0' //这个用于生成Java代码
compileOnly 'com.google.auto.service:auto-service:1.0-rc4' //提供@AutoService注解
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4' // 用于生成注册服务文件
}
下一篇再分析生成MainActivity_ViewBinding的逻辑。
第三步
新建一个Android库,取名butterknife_runtime,是运行时使用,提供一个Butter Knife.bind(this);方法,完成绑定的属性初始化。
目录结构如下:
Utils类时查找工具类,里面封装了findViewById。
好了,至此需要的三个库都创建完成了,下面使用一下,看能不能正常运行:
app模块下的build.gradle依赖如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "com.example.ndk_2_3_2"
minSdkVersion 28
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "x86" //本地库的cpu架构
}
}
ndk {
abiFilters "x86" //指定第三方库的cup架构
}
// javaCompileOptions{
// annotationProcessorOptions.includeCompileClasspath = true
// }
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation project(':butterknife_annotations') //使用Bind View注解
annotationProcessor project(':butterknife_complier') //生成Binding文件
implementation project(":butterknife_runtime") // 提供 bind方法,完成属性初始化
// implementation 'com.jakewharton:butterknife:10.2.3'
// annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
}
可以看到,生成了MainActivity_ViewBinding,跑到手机上看看:
MainActivity代码如下:
package com.example.ndk_2_3_2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.butterknife_annotations.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@BindView(R.id.sample_text)
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
textView.setText(stringFromJNI()); //这里正确使用,说明绑定属性成功
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
}
好了,下一篇分析MainActivity_ViewBinding的生成过程。