扔物線學(xué)習(xí)筆記啊
目標(biāo) 小試牛刀:要實(shí)現(xiàn)類(lèi)似ButterKnife 綁定視圖
public class MainActivity extends AppCompatActivity {
@BindView(R.id.textView) TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InnerBinding.bind(this);
textView.setText("臥龍鳳雛");
}
}
一 反射加注解
簡(jiǎn)單實(shí)現(xiàn) 1.同模塊
public class InnerBinding {
public static void bind(MainActivity activity) {
activity.textView = activity.findViewById(R.id.textView);
}
}
添加反射
public class InnerBinding {
public static void bind(Activity activity) {
//activity.textView = activity.findViewById(R.id.textView);
//如果有多個(gè)控件 TextViw ImageView 需要反射
// 1.遍歷所有的Field
for (Field field:activity.getClass().getDeclaredFields()){
//2.如果Filed 是BindView注解(前面有BindView注解的作用就來(lái)了)
BindView bindView = field.getAnnotation(BindView.class);
//3.如果BindView非空枢希,拿到值(例如R.id.textView)
if (bindView!=null){
try {
//4.賦值
field.set(activity,activity.findViewById(bindView.value()));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
移動(dòng)到lib-reflection模塊丐枉,運(yùn)行報(bào)錯(cuò)
因?yàn)榇藭r(shí)TextView不是public,需要擴(kuò)大反射權(quán)限
//5.擴(kuò)大訪問(wèn)權(quán)限
field.setAccessible(true);
完成通過(guò)反射bind
ButterKnife 不是依賴注入髓霞,是視圖綁定
二 工具類(lèi)加反射
通過(guò)在一個(gè)MainActivityBinding完成綁定操作冕杠,Binding只實(shí)例化MainActivityBinding
MainActivityBinding.java
public class MainActivityBinding {
//初始化就設(shè)置
public MainActivityBinding(MainActivity activity) {
activity.textView = activity.findViewById(R.id.mTv);
}
}
Binding.java
public class Binding {
public static void bind(Activity activity){
try {
//獲取類(lèi)
Class bindingClass = Class.forName(activity.getClass().getCanonicalName() + "Binding");
//獲取構(gòu)造方法
Constructor constructor = bindingClass.getDeclaredConstructor(activity.getClass());
constructor.newInstance(activity);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Binding.bind(this);
textView.setText("臥龍鳳雛");
}
}
三 反射加注解生成工具類(lèi)
1.要通過(guò)注解自動(dòng)生成 MainActivityBinding
- 1.1創(chuàng)建一個(gè) Module java or kotlin library 例如lib_processor
- 1.2配置 固定的文件目錄格式 resources =》META-INF=》services=》javax.annotation.processing.Processor 添加映射
- 1.3app模塊添加依賴 annotationProcessor
- 1.4專門(mén)為注解創(chuàng)建一個(gè)模塊 例如 lib_annoration 讓后其他需要用的地方添加依賴
項(xiàng)目結(jié)構(gòu)
- 生成代碼工具 Filer
- 用 javapoet 來(lái)生成的代碼
BindingProcessor.java
/**
* 注解處理的處理
* 生成代碼 processor
* 在編譯前執(zhí)行
*/
public class BindingProcessor extends AbstractProcessor {
Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
filer = processingEnvironment.getFiler();
}
/**
* package com.example.annotation;
*
* public class MainActivityBinding {
* public MainActivityBinding(MainActivity activity) {
* activity.textView = activity.findViewById(R.id.mTv);
* }
* }
*/
/**
* 進(jìn)行具體的注解處理
*
* @param set
* @param roundEnvironment
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
for (Element element : roundEnvironment.getRootElements()) {
String packageStr = element.getEnclosingElement().toString();
String classStr = element.getSimpleName().toString();
ClassName className = ClassName.get(packageStr,classStr+"Binding");
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(ClassName.get(packageStr,classStr),"activity");
boolean hasBinding = false;
for (Element enclosedElement:element.getEnclosedElements()){
if (enclosedElement.getKind() == ElementKind.FIELD) {
BindView bindView = enclosedElement.getAnnotation(BindView.class);
if (bindView!=null){
hasBinding = true;
constructorBuilder.addStatement("activity.$N = activity.findViewById($L)",
enclosedElement.getSimpleName(),bindView.value());
}
}
}
TypeSpec builtClass = TypeSpec.classBuilder(className)
.addModifiers(Modifier.PUBLIC)
.addMethod(constructorBuilder.build())
.build();
if (hasBinding){
try {
JavaFile.builder(packageStr,builtClass)
.build().writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 進(jìn)行注解處理的類(lèi)型
*
* @return
*/
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(BindView.class.getCanonicalName());
}
}
BindView.java
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}