接下來實操寫一遍,這里只使用BindView一個注解,來學(xué)習(xí)其實現(xiàn)過程。
第一步
新建一個Java庫,取名butterknife_annotations
目錄結(jié)構(gòu)如下,這里只有一個注解類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
其目錄如下:

這個類就是用來查找支持的注解,并執(zhí)行怎么生成代碼的邏輯,不能調(diào)試代碼,可以通過打印日志來查看指定位置的執(zhí)行情況。這個是在編譯期執(zhí)行的,具體來說就是Javac來執(zhí)行它,javac啟動一個完整Java虛擬機來運行注解處理器,所以需要將這個類注冊到Javac中。
有兩種方式注冊
-
需要在 butterknife_complier庫的 main 目錄下新建 resources 資源文件夾;
在 resources文件夾下建立 META-INF/services 目錄文件夾;
在 META-INF/services 目錄文件夾下創(chuàng)建 javax.annotation.processing.Processor 文件;
在 javax.annotation.processing.Processor 文件寫入注解處理器的全稱,包括包路徑;
目錄如圖所示:
image.png
在文件中寫入注解處理器的全路徑:
-
第一種手動添加的方式未免有些麻煩,并且容易出錯,可以借助一個庫自動生成
在自定義注解處理器類的頂部加入注解:
@AutoService(Processor.class),這個注解處理器是Google開發(fā)的,可以用來生成 META-INF/services/javax.annotation.processing.Processor 文件信息。
如下圖所示:
image.png
編譯之后會自動生成如第一種方式添加的文件,可以在butterknife_complier/build目錄下查看生成結(jié)果:

當(dāng)然這里依賴要添加正確,不然可能會報錯,依賴如下:
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基礎(chǔ)庫
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' // 用于生成注冊服務(wù)文件
}
下一篇再分析生成MainActivity_ViewBinding的邏輯。
第三步
新建一個Android庫,取名butterknife_runtime,是運行時使用,提供一個Butter Knife.bind(this);方法,完成綁定的屬性初始化。
目錄結(jié)構(gòu)如下:

Utils類時查找工具類,里面封裝了findViewById。
好了,至此需要的三個庫都創(chuàng)建完成了,下面使用一下,看能不能正常運行:
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架構(gòu)
}
}
ndk {
abiFilters "x86" //指定第三方庫的cup架構(gòu)
}
// 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的生成過程。

