butterknife架构核心
来源:互联网 发布:淘宝的等级怎么升级快 编辑:程序博客网 时间:2024/06/06 09:08
反射:
Class.forName("com.mysql.jdbc.Driver");
在编写代码,编译的时候,这个类没有,但是在运行的时候,这个Driver.class类有。
Mirror模块
让java源文件在编译的时候,可以访问
APT 命令行工具
1.编译过程中,需要获取哪些类的信息?
2.这些类的信息在哪里获取?
APT会访问AnnotationProcessor类,获取访问规则,然后访问符合规则的A类,访问到了A类的属性,方法集合,这些信息又会传给Process处理。
核心类代码
1、ViewInjectHandler.java
把RoundEnvironment类整理出一个Map
public class ViewInjectHandler implements AnnotationHandler { ProcessingEnvironment mProcessingEnv; @Override public void attachProcessingEnv(ProcessingEnvironment processingEnv) { mProcessingEnv = processingEnv; }@Overridepublic Map<String,List<VariableElement>> handleAnnotation(RoundEnvironment roundEnv){ Map<String, List<VariableElement>> annotationMap = new HashMap<String, List<VariableElement>>(); //获取使用ViewInjector注解的所有元素 Set<? extends Element> elementSet = roundEnv.getElementsAnnotatedWith(ViewInjector); for(Element element : elementSet){ //注解的字段 VariableElement varElement = (VariableElement)element; //获取某个字段所属的类的完整路径 String className = getParentClassName(varElement); //获取这个类上所有带有ViewInjector注解的字段 List<VariableElement> cacheElements = annotationMap.get(className); if (cacheElements == null) { cacheElements = new LinkedList<VariableElement>(); } //将元素添加到该类型对应的字段列表中 cacheElements.add(varElement); //以类的路径为key,字段列表为value,存入map //这里是将所在字段按所属的类型进行分类 annotationMap.put(className, cacheElements); }}/***获取某个字段所属的类的完整路径*/private String getParentClassName(VariableElement varElement) { //获取该元素所在的类型,例如某个View是某个Activity的字段,这里就是获取这个Activity的类型 TypeElement typeElement = (TypeElement)varElement.getEnclosingElement(); //获取typeElement的包名 String packageName = AnnotationUtil.getPackageName(mProcessingEnv, typeElement); //类型的完整路径名,比如某个Activity的完整路径 return packageName + "." + typeElement.getSimpleName().toString(); }}
2、ViewInjectorProcessor.java
符合规则的类在这里处理
//指定APT工具访问规则@SupportedAnnotationTypes("com.jasonknife.annotation.ViewInjector")@SupportedSourceVersion(SourceVersion.RELEASE_6)public class ViewInjectorProcessor extends AbstractProcessor {public List<AnnotationHandler> mHandlers = new ArrayList<AnnotationHandler>(); Map<String,List<VariableElement>> map = new HashMap<String,List<VariableElement>>();AdapterWriter mWriter;@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); registerHandlers(); //2.根据map生成辅助类 mWriter = new DefaultAdapterWriter(processingEnv);}private void registerHandlers(){ mHandlers.add(new ViewInjectHandler());} //符合规则的类信息,在这里处理 @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { //1.roundEnv->整理出Map<String, List<VariableElement>> (key->完整类名,value->属性集合) for(AnnotationHandler handler : mHandlers){ handler.attachProcessingEnv(processingEnv); map.putAll(handler.handleAnnotation(roundEnv)); } mWriter.generate(map); return true; }}
3、生成辅助类的Writer:AbstractWriter.java
public abstract class AbstractWriter implements AdapterWriter { private ProcessingEnvironment mProcessingEnv; private Filer mFiler; public AbstractWriter(ProcessingEnvironment env) { this.mProcessingEnv = env; this.mFiler = this.mProcessingEnv.getFiler(); } @Override public void generate(Map<String,List<VariableElement>> map) { //模板方法 Iterator<Entry<String, List<VariableElement>>> entry = map.entrySet().iterator(); while(iterator.hasNext()){ Entry<String,List<VariableElement>> entry = iterator.next(); //属性集合 List<VariableElement> cacheElements = entry.getValue(); if(cacheElements == null || cacheElements.size() == 0) { continue; } InjectInfo info = createInjectInfo(cacheElements.get(0)); //创建一个Java源文件 Writer writer = null; try{ JavaFileObject javaFileObject = mFiler.createSourceFile(info.getFullClassName()); writer = javaFileObject.openWriter(); //头部,模板方法只控制算法的骨架,具体的交给子类实现 generateImport(writer,info); for (VariableElement variableElement : cacheElements) { //属性部分 writeField(writer,variableElement,info); } //尾部 writeEnd(writer); }catch(IOException e){ e.printStackTrace(); }finally{ IOUtil.closeQuitly(writer); } }}private InjectInfo createInjectInfo(VariableElement variableElement) {//属性所属的类TypeElement typeElement = (TypeElement)variableElement.getEnclosingElement();String packageName = AnnotationUtil.getPackageName(mProcessingEnv,variableElement);String className = typeElement.getSimpleName().toString();return new InjectInfo(packageName,className);}/***生成头部*/protected abstract void generateImport(Writer writer,InjectInfo info) throws IOException;/***生成尾部*/protected abstract void writeField(Writer writer,VariableElement element,InjectInfo info);/***产生结尾部分*/protected abstract void writeEnd(Writer writer) throws IOException;/***注入信息*/ class InjectInfo{ public String packageName; public String className; //辅助类的类名 public String newClassName; public InjectInfo(String packageName,String className) { this.packageName = packageName; this.className = className ; this.newClassName = className + JsonKnife.SUEFIX; } public String getFullClassName() { return this.packageName +"." +this.newClassName; } }}
4、具体生成辅助类的子类:DefaultAdapterWriter.java
public class DefaultAdapterWriter extends AbstractWriter { public DefaultAdapterWriter(ProcessingEnvironment processingEnv) { super(processingEnv); }@Overrideprotected void generateImport(Writer writer, InjectInfo info) throws IOException { writer.write("package "+info.packageName +";"); writer.write("\n\n"); writer.write("import com.jasonknife.adapter.InjectAdapter;"); writer.write("\n"); writer.write("import com.jasonknife.util.ViewFinder;"); writer.write("\n\n\n"); writer.write("/*This Class is generated by JasonKnife, do not modify!*/"); writer.write("\n"); writer.write("public class "+info.newClassName+" implements InjectAdapter<"+info.); writer.write("\n\n"); writer.write("public void injects("+info.className+" target) {"); writer.write("\n"); }@Overrideprotected void writeField(Writer writer, VariableElement element, InjectInfo info) throw IOException { ViewInjector viewInjector = element.getAnnotation(ViewInjector.class); int id = viewInjector.value(); String fieldName = element.getSimpleName().toString(); writer.write("target."+fieldName+" = ViewFinder.findViewById(target, "+id+");"); writer.write("\n");}@Overrideprotected void writeEnd(Writer writer)throws IOException { writer.write(" }"); writer.write("\n\n"); writer.write("}");}}
得到辅助类MainActivity$InjectAdapter.java
这个类里面的injects方法才是给控件赋值的真正方法
public class MainActivity$InjectAdapter implements InjectAdapter { public void injects(MainActivity target) { target.text = ViewFinder.findViewById(target,2131099648); target.btn = ViewFinder.findViewById(target,2131099649); }}
编写注入类:
public final class JsonKnife { public static final String SUEFIX ="$InjectAdapter"; public static void inject(Activity activity){ InjectAdapter<Activity> adapter = getViewAdapter(activity.getClass()); adapter.injects(activity); }/***获取辅助类实例*/private static <T> InjectAdapter<T> getViewAdapter(Class<?> clazz) { InjectAdapter<T> adapter = null; String adapterClsName = clazz.getName() + SUEFIX; try{ Class<?> adapterClazz = Class.forName(adapterClsName); adapter = adapterClazz.newInstance(); }catch(Exception e){ e.printStackTrace(); } //NullAdapter 空对象模式 return adapter == null ? new NullAdapter : adapter;}}
使用方法
public class MainActivity extends Activity implements OnClickListener { @ViewInject(R.id.text) protected TextView text; @ViewInject(R.id.button) protected Button btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); JsonKnife.inject(this); btn.setOnClickListener(this); } public void onClick(View v){ Log.d("json","按钮不为空,注入成功..."); }}
阅读全文
0 0
- butterknife架构核心
- mvp+okgo+butterknife搭建android app架构
- tomcat架构:核心架构模块
- ButterKnife
- ButterKnife
- ButterKnife
- ButterKnife
- ButterKnife
- ButterKnife
- ButterKnife
- butterknife
- ButterKnife
- ButterKnife
- Butterknife
- butterknife
- ButterKnife
- ButterKnife
- butterknife
- 数学1(n^n)Leftmost Digit
- find命令进阶用法(一)
- 易语言操作sql server完整教程
- android gradle统一版本
- TCL笔记
- butterknife架构核心
- L1-011. A-B
- 简单的存储过程
- Win7下svchost.exe占用内存过多
- Redis基础
- 网络编程之解析网页
- history
- [ JS 进阶 ] Ajax 详解 (1) :XHR 对象
- easy ffmpeg