动脑学院-手写ButterKnife框架(不包含自动生成代码)
Posted 天耀106
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动脑学院-手写ButterKnife框架(不包含自动生成代码)相关的知识,希望对你有一定的参考价值。
1、目录结构
2、butterknife-annotions新增一个BindView接口
package lwl.tianyao.butterknife_annotions;
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.SOURCE)
public @interface BindView
int value();
3、bufferknife-compiler
1)build.gradle添加依赖
具体名称:
api 'com.google.auto.service:auto-service:1.0-rc3'
implementation project(':butterknife-annotions')
tasks.withType(JavaCompiler)
options.encoding = "UTF-8"
2)新建一个类ButterKnifeProcess继承AbstractProcessor
package lwl.tianyao.bufferknife_compiler;
import com.google.auto.service.AutoService;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaFileObject;
import lwl.tianyao.butterknife_annotions.BindView;
@AutoService(Processor.class)
public class ButterKnifeProcess extends AbstractProcessor
protected ProcessingEnvironment processingEnv;
private boolean initialized = false;
//1.我们要处理哪些注解
@Override
public Set<String> getSupportedAnnotationTypes()
Set<String> types= new LinkedHashSet<>();
types.add(BindView.class.getCanonicalName());
return types;
//2.添加支持JDK的支持
@Override
public SourceVersion getSupportedSourceVersion()
return SourceVersion.latestSupported();
//3.定义一个用生成java文件的对象
Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment)
super.init(processingEnvironment);
processingEnv = processingEnvironment;
filer=processingEnvironment.getFiler();
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment)
//set保存了所有带注解的位置的相关信息
//取到所有含有BindView注解的java文件的信息
Set<? extends Element> elementSet = roundEnvironment.getElementsAnnotatedWith(BindView.class);
//进行分类 key--类名 value --所有的成员变量
Map<String,List<VariableElement>> cacheMap = new HashMap<>();
for(Element element:elementSet)
VariableElement variableElement = (VariableElement) element;
String activityName = getActivityName(variableElement);
List<VariableElement> list = cacheMap.get(activityName);
//判断一下,是否以前有分类
if(list==null)
list = new ArrayList<>();
cacheMap.put(activityName,list);
list.add(variableElement);
Iterator iterator = cacheMap.keySet().iterator();
while (iterator.hasNext())
//准备生成的java文件的信息
//1.Activity的名字
String activity = (String) iterator.next();
//2.获取当前activity中所有的成员
List<VariableElement> cacheElements = cacheMap.get(activity);
//3.获取包名
String packageName = getPackageName(cacheElements.get(0));
//4.获取要生成的文件的类名
String newActivityBinder = activity+"$ViewBinder";
Writer writer = null;
try
JavaFileObject javaFileObject = filer.createSourceFile(newActivityBinder);
writer = javaFileObject.openWriter();
String activitySimpleName = cacheElements.get(0)
.getEnclosingElement().getSimpleName().toString()+"$ViewBinder";
//写入文件中
writer.write("package "+packageName+" ;");
writer.write("\\n");
writer.write("import "+packageName+".ViewBinder;");
writer.write("\\n");
writer.write("public class "+activitySimpleName+" implements ViewBinder<"+activity+">");
writer.write("\\n");
writer.write("public void bind("+activity+" target)");
writer.write("\\n");
for(VariableElement variableElement:cacheElements)
BindView bindView = variableElement.getAnnotation(BindView.class);
//取到成员变量名
String fieldName = variableElement.getSimpleName().toString();
//取成员变量的类型
TypeMirror typeMirror = variableElement.asType();
writer.write("target."+fieldName+"=("+typeMirror.toString()+")target.findViewById("+bindView.value()+");");
writer.write("\\n");
writer.write("");
writer.write("\\n");
writer.write("");
writer.write("\\n");
writer.close();
catch (Exception e)
e.printStackTrace();
return false;
private String getActivityName(VariableElement variableElement)
String packageName=this.getPackageName(variableElement);
Element typeElement = variableElement.getEnclosingElement();
return packageName+"."+typeElement.getSimpleName().toString();
private String getPackageName(VariableElement variableElement)
Element typeElement = variableElement.getEnclosingElement();
String packageName = processingEnv.getElementUtils()
.getPackageOf(typeElement)
.getQualifiedName()
.toString();
return packageName;
3)最终生成的java文件
package lwl.tianyao.bufferknifeproject ;
import lwl.tianyao.bufferknifeproject.ViewBinder;
public class MyActivity$ViewBinder implements ViewBinder<lwl.tianyao.bufferknifeproject.MyActivity>
public void bind(lwl.tianyao.bufferknifeproject.MyActivity target)
target.btn=(android.widget.Button)target.findViewById(2131165218);
4、主项目
1)新增ViewBinder接口
package lwl.tianyao.bufferknifeproject;
public interface ViewBinder<T>
public void bind(T target);
2)新增ButterKnife类
package lwl.tianyao.bufferknifeproject;
import android.app.Activity;
public class ButterKnife
public static void bind(Activity activity)
String className =activity.getClass().getName()+"$ViewBinder";
try
Class<?> viewBindClass = Class.forName(className);
ViewBinder viewBinder = (ViewBinder) viewBindClass.newInstance();
viewBinder.bind(activity);
catch (Exception e)
e.printStackTrace();
3)Acitivity的代码
package lwl.tianyao.bufferknifeproject;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import lwl.tianyao.butterknife_annotions.BindView;
public class MyActivity extends Activity
@BindView(R.id.btn)
Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
public void click(View view)
Toast.makeText(this,btn.toString(),Toast.LENGTH_SHORT).show();
4)布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:onClick="click"
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
最后一步,编译运行如果能正常显示btn按钮的字符串信息则说明绑定成功了。
代码下载地址: 点击打开链接
以上是关于动脑学院-手写ButterKnife框架(不包含自动生成代码)的主要内容,如果未能解决你的问题,请参考以下文章