Android仿butterKnife,練習(xí)APT技術(shù)(二)

接下來實操寫一遍,這里只使用BindView一個注解,來學(xué)習(xí)其實現(xiàn)過程。

第一步

新建一個Java庫,取名butterknife_annotations
目錄結(jié)構(gòu)如下,這里只有一個注解類BindView

image.png

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
其目錄如下:

image.png

這個類就是用來查找支持的注解,并執(zhí)行怎么生成代碼的邏輯,不能調(diào)試代碼,可以通過打印日志來查看指定位置的執(zhí)行情況。這個是在編譯期執(zhí)行的,具體來說就是Javac來執(zhí)行它,javac啟動一個完整Java虛擬機來運行注解處理器,所以需要將這個類注冊到Javac中。
有兩種方式注冊

  1. 需要在 butterknife_complier庫的 main 目錄下新建 resources 資源文件夾;
    在 resources文件夾下建立 META-INF/services 目錄文件夾;
    在 META-INF/services 目錄文件夾下創(chuàng)建 javax.annotation.processing.Processor 文件;
    在 javax.annotation.processing.Processor 文件寫入注解處理器的全稱,包括包路徑;
    目錄如圖所示:


    image.png

    在文件中寫入注解處理器的全路徑:

  2. 第一種手動添加的方式未免有些麻煩,并且容易出錯,可以借助一個庫自動生成
    在自定義注解處理器類的頂部加入注解:
    @AutoService(Processor.class),這個注解處理器是Google開發(fā)的,可以用來生成 META-INF/services/javax.annotation.processing.Processor 文件信息。
    如下圖所示:


    image.png

    編譯之后會自動生成如第一種方式添加的文件,可以在butterknife_complier/build目錄下查看生成結(jié)果:

image.png

當(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)如下:

image.png

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'
}
image.png

可以看到,生成了MainActivity_ViewBinding,跑到手機上看看:


image.png

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的生成過程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容