ButterKnife注解框架相信大家都是用過,記得以前的老大老是說黃油刀毁菱,黃油刀的瑰谜,那里面的實現(xiàn)原理是什么呢?其實內(nèi)部原理比較簡單侈离, 簡單的你看文本文也可以自己寫
編譯時注解實現(xiàn)
1,定義接口试幽,成員變量的
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.RUNTIME)
public @interface InjectView {
int value();
}
這個injectView 接口的名字可以自己定義,但一般做到見名知意里面的@Target 等注解看統(tǒng)一專題里面的詳解卦碾。都是注解的內(nèi)容铺坞,里面的是生命周期等屬性的限制
2.定義點擊事件的接口
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {
int[] value();
}
3.寫一個工具類也就是相當(dāng)于 Butterknife.bind(this)效果:
/**
* 文件描述: 代碼注入工具類
* Created by xn069392
* 創(chuàng)建時間 2018/8/2
*/
public class InjectViewUtils {
/**
* 代碼注入方法,相當(dāng)于Butterknife的 bind()
*
* @param activity
*/
public static void inject(final Activity activity) {
//反射拿到類對象
Class<? extends Activity> clazz = activity.getClass();
//這里我們需要的是所有的成員變量的參數(shù)
Field[] Fileds = clazz.getDeclaredFields();
//遍歷集合
for (int i = 0; i < Fileds.length; i++) {
//獲取每一個成員變量
Field filed = Fileds[i];
// 如果私有 暴力反射
filed.setAccessible(true);
//獲取到成員變量的注解洲胖,傳入?yún)?shù)就是之前我們定義的接口的類對象
InjectView inject = filed.getAnnotation(InjectView.class);
if (inject != null) {
//我們的接口中定義了一個int 類型的value 值 康震,獲取到value 也就是我們成員變量的id
int id = inject.value();
//通過這個ID,也是需要在傳入Activity中去找到對應(yīng)view的
View view = activity.findViewById(id);
//成員變量找到了宾濒,這個要去設(shè)置
try {
filed.set(activity, view);
} catch (IllegalAccessException e) {
Log.e(TAG, "inject: 設(shè)置成員變量失斖榷獭!");
e.printStackTrace();
}
}
}
//處理點擊事件
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
final Method method = declaredMethods[i];
method.setAccessible(true);
OnClick onClick = method.getAnnotation(OnClick.class);
//為什么是一個數(shù)組呢,因為我們的點擊事件 有事后就寫一個方法橘忱,多個id .
int[] value = onClick.value();
for (int j = 0; j < value.length; j++) {
int idValue = value[j];
final View viewById = activity.findViewById(idValue);
viewById.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(activity, viewById);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
上面的代碼主要是用到暴力反射赴魁,
4.在主方法中調(diào)用
public class MainActivity extends AppCompatActivity {
@InjectView(R.id.button1)
Button mButton;
@InjectView(R.id.button2)
Button mButton2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectViewUtils.inject(this);
mButton.setText("我是第一個button");
}
@OnClick({R.id.button1,R.id.button2})
private void XXX(View view ){
switch (view.getId()){
case R.id.button1:
Toast.makeText(this,"第一個按鈕的手動編譯時注解",Toast.LENGTH_LONG).show();
break;
case R.id.button2:
Toast.makeText(this,"第222個按鈕的手動編譯時注解,主要用到反射",Toast.LENGTH_LONG).show();
break;
}
}
}package com.xiaoniu.finance.butterknifesimple;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static android.content.ContentValues.TAG;
/**
* 文件描述: 代碼注入工具類
* Created by xn069392
* 創(chuàng)建時間 2018/8/2
*/
public class InjectViewUtils {
/**
* 代碼注入方法,相當(dāng)于Butterknife的 bind()
*
* @param activity
*/
public static void inject(final Activity activity) {
//反射拿到類對象
Class<? extends Activity> clazz = activity.getClass();
//這里我們需要的是所有的成員變量的參數(shù)
Field[] Fileds = clazz.getDeclaredFields();
//遍歷集合
for (int i = 0; i < Fileds.length; i++) {
//獲取每一個成員變量
Field filed = Fileds[i];
// 如果私有 暴力反射
filed.setAccessible(true);
//獲取到成員變量的注解钝诚,傳入?yún)?shù)就是之前我們定義的接口的類對象
InjectView inject = filed.getAnnotation(InjectView.class);
if (inject != null) {
//我們的接口中定義了一個int 類型的value 值 颖御,獲取到value 也就是我們成員變量的id
int id = inject.value();
//通過這個ID,也是需要在傳入Activity中去找到對應(yīng)view的
View view = activity.findViewById(id);
//成員變量找到了凝颇,這個要去設(shè)置
try {
filed.set(activity, view);
} catch (IllegalAccessException e) {
Log.e(TAG, "inject: 設(shè)置成員變量失斉斯啊!");
e.printStackTrace();
}
}
}
//處理點擊事件
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
final Method method = declaredMethods[i];
method.setAccessible(true);
OnClick onClick = method.getAnnotation(OnClick.class);
//為什么是一個數(shù)組呢拧略,因為我們的點擊事件 有事后就寫一個方法芦岂,多個id .
//這里有的方法沒有注解,必須做空判斷
if(onClick !=null){
int[] value = onClick.value();
for (int j = 0; j < value.length; j++) {
int idValue = value[j];
final View viewById = activity.findViewById(idValue);
viewById.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
method.invoke(activity, viewById);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}
5.效果的實現(xiàn)
inject.gif
6.源碼地址:
https://github.com/zh2016hz/ButterknifeSimple.git