Android自定义注解
ElementType.Type
|
接口、类、注解、枚举
|
ElementType.FIELD
|
字段、枚举常量
|
ElementType.METHOD
|
方法 |
ElementType.PARAMETER
|
方法参数
|
ElementType.CONSTRUCOTOR
|
构造函数
|
ElementType.LOCAL_VARIABLE
|
局部变量
|
ElementType.ANNOTATION_TYPE
|
注解
|
Element.PACKAGE
|
包
|
RetentionPolicy.SOURCE
|
源文件,当java文件被编译成class文件时,注解失效
|
RetentionPolicy.CLASS
|
注解存在class 文件,当jvm 加载class文件时,注解生效,默认指定的参数
|
RetentionPolicy.RUNTIME
|
注解保存到class文件,jvm加载class文件后,依然有效
|
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* author: rexkell
* explain:
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoCreateObject {
}
2.2解析注解
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; /**
* author: rexkell
* explain:
*/
public class AutoCreateProcess {
public static void bind(final Object object){
Class parentClass=object.getClass();
Field[] fields= parentClass.getFields();
for (Field field: fields){
AutoCreateObject autoCreateObject= field.getAnnotation(AutoCreateObject.class);
if (autoCreateObject!=null){
field.setAccessible(true);
try {
Class<?> autoCreateClass= field.getType();
Constructor autoCreateConstructor= autoCreateClass.getConstructor();
field.set(object,autoCreateConstructor.newInstance());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}catch (IllegalAccessException e){
e.printStackTrace();
}catch (InvocationTargetException e){
e.printStackTrace();
}catch (InstantiationException e){
e.printStackTrace();
} }
}
}
}
@AutoCreateObject
Students students;
//创建对象
AutoCreateProcess.bind(this);
3、模拟bindViewId
3.1、创建一个java Module
implementation 'com.squareup:javapoet:1.9.0'
implementation 'com.google.auto.service:auto-service:1.0-rc2'
3.2 申明注解
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* author: rexkell
* explain:
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.CLASS)
public @interface BindView {
int value() default -1;
}
3.3 解析注解
import android.app.Activity; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map; /**
* author: rexkell
* explain:
*/
public class MyBindView {
private static Map<Class, Method> classMethodMap=new HashMap<>();
public static void bind(Activity target){
if (target!=null){
Method method = classMethodMap.get(target.getClass());
try {
if (method==null){
//获取编译生成的注解类
String bindClassName= target.getPackageName()+".Bind"+target.getClass().getSimpleName();
Class bindClass=Class.forName(bindClassName);
method=bindClass.getMethod("bindView",target.getClass());
classMethodMap.put(target.getClass(),method);
}
method.invoke(null,target);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
由于是编译时产生的注解,需要通过 extends AbstractProcessor 来实现
import com.google.auto.service.AutoService;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec; import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set; import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements; /**
* author: rexkell
* explain:
*/
@AutoService(Processor.class)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class BindProcess extends AbstractProcessor {
private Elements mElementsUtil;
private Map<TypeElement,Set<Element>> mBindViewElems; @Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
mElementsUtil=processingEnv.getElementUtils();
mBindViewElems=new HashMap<>(); } @Override
public Set<String> getSupportedAnnotationTypes() {
//添加需要解析的自定义注解类
Set<String> types=new HashSet<>();
types.add(BindView.class.getCanonicalName());
types.add(BindLayout.class.getCanonicalName());
return types;
} @Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
System.out.println("Process start!");
initBindElems(roundEnv.getElementsAnnotatedWith(BindView.class));
generateJavaClass();
System.out.println("Process finish!");
return true;
}
//初始化绑定的控件
private void initBindElems(Set<? extends Element> bindElems){
for (Element bindElem : bindElems){
TypeElement enclosedElem=(TypeElement) bindElem.getEnclosingElement();
Set<Element> elems=mBindViewElems.get(enclosedElem);
if (elems==null){
elems=new HashSet<>();
mBindViewElems.put(enclosedElem,elems);
System.out.println(enclosedElem.getSimpleName());
}
elems.add(bindElem);
System.out.println("Add bind elem "+bindElem.getSimpleName());
}
}
private void generateJavaClass(){
//生成Bind+ClassName+.class 文件,文件内容实现findViewById
for (TypeElement enclosedElem: mBindViewElems.keySet()){
MethodSpec.Builder methodSpesBuilder = MethodSpec.methodBuilder("bindView")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.addParameter(ClassName.get(enclosedElem.asType()),"activity")
.returns(TypeName.VOID);
BindLayout bindLayoutAnno =enclosedElem.getAnnotation(BindLayout.class);
if (bindLayoutAnno!=null){
methodSpesBuilder.addStatement(String.format(Locale.US,"activity.setContentView(%d)",bindLayoutAnno.value()));
}
for (Element bindElem : mBindViewElems.get(enclosedElem)){
methodSpesBuilder.addStatement(String.format(Locale.US,"activity.%s=(%s)activity.findViewById(%d)",
bindElem.getSimpleName(),bindElem.asType(),bindElem.getAnnotation(BindView.class).value()));
}
TypeSpec typeSpec=TypeSpec.classBuilder("Bind"+enclosedElem.getSimpleName())
.superclass(TypeName.get(enclosedElem.asType()))
.addModifiers(Modifier.FINAL,Modifier.PUBLIC)
.addMethod(methodSpesBuilder.build())
.build();
JavaFile file = JavaFile.builder(getPackageName(enclosedElem),typeSpec).build();
try {
file.writeTo(processingEnv.getFiler());
} catch (IOException e) {
e.printStackTrace();
} }
}
private String getPackageName(TypeElement typeElement){
return mElementsUtil.getPackageOf(typeElement).getQualifiedName().toString();
} }
3.4 在需要使用bindViewId 注解中引入模块。
@BindView(R.id.edt_longitude)
EditText edtLongitude;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences sharedPreferences= this.getSharedPreferences("theme",MODE_PRIVATE);
int themeId=sharedPreferences.getInt("themeId",2);
if (themeId==1){
setTheme(R.style.BaseAppThemeNight);
}else if (themeId==0){
setTheme(R.style.AppTheme);
}
setContentView(R.layout.activity_main);
MyBindView.bind(this);
}
Android自定义注解的更多相关文章
- Android 自定义注解(Annotation)
现在市面上很多框架都有使用到注解,比如butterknife库.EventBus库.Retrofit库等等.也是一直好奇他们都是怎么做到的,注解的工作原理是啥.咱们能不能自己去实现一个简单的注解呢. ...
- Android自定义工具类获取按钮并绑定事件(利用暴力反射和注解)
Android中为按钮绑定事件的有几种常见方式,你可以在布局文件中为按钮设置id,然后在MainActivity中通过findViewById方法获取按钮对象实例,再通过setOnClickListe ...
- Android面试基础(一)IOC(DI)框架(ViewUtils)讲解_反射和自定义注解类
1. Android中的IOC(DI)框架 1.1 ViewUtils简介(xUtils中的四大部分之一) IOC: Inverse of Controller 控制反转. DI: Dependenc ...
- 【转】ANDROID自定义视图——onLayout源码 流程 思路详解
转载(http://blog.csdn.net/a396901990) 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量——onMeasure():决定View的大小 2.布局 ...
- java自定义注解类
一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...
- android 自定义动画
android自定义动画注意是继承Animation,重写里面的initialize和applyTransformation,在initialize方法做一些初始化的工作,在applyTransfor ...
- Jackson 通过自定义注解来控制json key的格式
Jackson 通过自定义注解来控制json key的格式 最近我这边有一个需求就是需要把Bean中的某一些特殊字段的值进行替换.而这个替换过程是需要依赖一个第三方的dubbo服务的.为了使得这个转换 ...
- 自定义注解之运行时注解(RetentionPolicy.RUNTIME)
对注解概念不了解的可以先看这个:Java注解基础概念总结 前面有提到注解按生命周期来划分可分为3类: 1.RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成clas ...
- JAVA自定义注解
在学习使用Spring和MyBatis框架的时候,使用了很多的注解来标注Bean或者数据访问层参数,那么JAVA的注解到底是个东西,作用是什么,又怎样自定义注解呢?这篇文章,即将作出简单易懂的解释. ...
随机推荐
- Geohash精度和原理
转自:https://blog.csdn.net/u011497262/article/details/81210634 https://www.jianshu.com/p/1ecf03293b9a ...
- JAVA笔记 -- 访问权限控制
访问权限控制 没有权限控制的时候,由于所有的接口都是可以访问的.当一个类库部分代码,发现有更好的方法解决的时候,可能其他接口会发生改动.这会导致另一个地方的引用该类库的程序发生崩溃.为了解决这种问题, ...
- oracle12.2RAC之OGG安装配置(二)
本机到本机的配置: 源端 10.1.83.144:1521/SIBP_GSDY HNSIB_GSDY目标端 10.1.83.144:1521/SIBP_GS HN ...
- 自己写的一个连数据库的音乐调用模块 MusicRj
#自己定义 class MusicRj: # 创音乐表t_music # sql = '''CREATE TABLE t_music1( # id INT PRIMARY KEY AUTO_INCRE ...
- ThinkPHP数据库驱动之mysql事物回滚
1.开启事务方法 startTrans()2.事务提交方法 commit()3.事务回滚方法 rollback() 用法例子: $order = M(‘order’); $allAdded = tru ...
- oracle数据库自动生成数据库表结构文档(亲测有效)
import java.awt.Color; import java.io.FileOutputStream; import java.sql.Connection; import java.sql. ...
- VIJOS-P1167 南蛮图腾
洛谷 P1498 南蛮图腾 洛谷传送门 JDOJ 1325: VIJOS-P1167 南蛮图腾 JDOJ传送门 Description 自从到了南蛮之地,孔明不仅把孟获收拾的服服帖帖,而且还发现了不少 ...
- 新书上线:《Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统》,欢迎大家买回去垫椅子垫桌脚
新书上线 大家好,笔者的新书<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>已上线,此书内容充实.材质优良,乃家中必备垫桌脚 ...
- Codeforces Round #603 (Div. 2) B. PIN Codes 水题
B. PIN Codes A PIN code is a string that consists of exactly 4 digits. Examples of possible PIN code ...
- settings.py相关配置
INSTALLED_APPS #配置项目绑定的应用 TEMPLATES #配置项目使用的模板引擎 DATABASES #设定绑定的数据库 TIME_ZONE #设定时区,时区的设定可能 ...