敬請期待....
可以先參考:https://www.jianshu.com/p/e6912e9069d3
一. 使用背景
如果沒用過ViewBinding, 可以先去了解下. Android ViewBinding的使用
對於findViewById和OnClick,大部分時候, 我們使用ButterKnife就可以了,但是呢,谷歌後面出了DataBinding和Viewbinding來解決findViewById的問題,用了這兩個以後,估計大家也不會使用ButterKnife. 那麼問題來了,OnClick怎麼處理呢? 直接手寫嗎? 所以就寫了一個針對Onclick處理的小插件. 如下圖:
解決的問題:
1. 每次都需要手動寫重複的代碼.
2. 在lib中,id無法用Switch(viewId)
二. 引用插件方式
File---settings---Plugins. 搜索OnClickMe
如果Android studio搜索不到插件?
點擊File | Settings | Appearance & Behavior | System Settings | Updates 記住 Use secure connection(不要勾選),如果勾選就取消,然後重啓
三. 使用方式
①. 和ButterKnife差不多,鼠標右鍵 選中佈局(activity_main 或 ActivityMainBinding)---generate----OnClickMe.
②.項目首次使用, 需要勾選“生成解析類”,重新編譯一下即可生成對應的類,生成的類在 src/java/liys/click下
OnClickUtils.init(Activity activity); //Activity中使用
OnClickUtils.init(Object target, View view); //Fragment或其它地方使用
四.關於性能問題
解析使用的是反射,原因有3個:
- 一般的App,一個頁面能有多少個點擊監聽?用不用反射,我們人體是察覺不到有什麼變化的.
- 手機硬件也在不斷的升級,影響只會越來越小.
- 可以節約一些開發時間.
五.工具類源碼
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AClick {
@IdRes int[] value() default { View.NO_ID };
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AClickStr {
String[] value() default {""};
}
public class OnClickUtils {
public static void init(Activity target){
View sourceView = target.getWindow().getDecorView();
initClick(target, sourceView);
}
public static void init(Object target, View view){
initClick(target, view);
}
private static void initClick(@NonNull final Object target, @NonNull View source){
String packageName = source.getContext().getPackageName();
final Method[] methods = target.getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
boolean hasAnno = methods[i].isAnnotationPresent(AClick.class);
if(hasAnno){
AClick aClick = methods[i].getAnnotation(AClick.class);
assert aClick != null;
int[] ids = aClick.value();
for (int j = 0; j < ids.length; j++) {
final int finalI = i;
source.findViewById(ids[j]).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
methods[finalI].invoke(target, v);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
boolean hasAnnoStr = methods[i].isAnnotationPresent(AClickStr.class);
if(hasAnnoStr){
AClickStr aClick = methods[i].getAnnotation(AClickStr.class);
final String[] ids = aClick.value();
for (int j = 0; j < ids.length; j++) {
final int finalI = i;
int id = 0;
try {
Class clazz = Class.forName(packageName+".R$id");
Field field = clazz.getDeclaredField(ids[j]);
id = (int)field.get(null);
} catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException e) {
e.printStackTrace();
}
if(id==0){
continue;
}
final int finalJ = j;
source.findViewById(id).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
methods[finalI].invoke(target, v, ids[finalJ]);
}catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
});
}
}
}
}
}