自定义Android 注解
来源:互联网 发布:辅助驾驶软件 编辑:程序博客网 时间:2024/05/13 23:28
基础介绍
Java注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
(1)元注解
元注解是指注解的注解。有@Retention @Target @Document @Inherited这四种。
(2)@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
(3)@Target:定义注解的作用目标
其定义的源码为:
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
(4)@Document:说明该注解将被包含在javadoc中
(5)@Inherited:说明子类可以继承父类中的该注解
举个栗子
这个例子实现了一个findViewById功能。
注解
package com.example.basedemo.annotation.diy;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.RUNTIME)public @interface ViewInject { int value(); /* parent view id */ int parentId() default 0;}
注解处理
package com.example.basedemo.annotation.diy;import android.app.Activity;import android.view.View;import java.lang.reflect.Field;public class ViewUtils { private ViewUtils() { } public static void inject(Activity activity) { injectObject(activity, new ViewFinder(activity)); } @SuppressWarnings("ConstantConditions") private static void injectObject(Object handler, ViewFinder finder) { Class<?> handlerType = handler.getClass(); // inject view Field[] fields = handlerType.getDeclaredFields(); if (fields != null && fields.length > 0) { for (Field field : fields) { ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) { try { View view = finder.findViewById(viewInject.value(), viewInject.parentId()); if (view != null) { field.setAccessible(true); field.set(handler, view); } } catch (Throwable e) { e.printStackTrace(); } } } } }}
package com.example.basedemo.annotation.diy;import android.app.Activity;import android.view.View;public class ViewFinder { private Activity activity; public ViewFinder(Activity activity) { this.activity = activity; } public View findViewById(int id) { return activity.findViewById(id); } public View findViewById(int id, int pid) { View pView = null; if (pid > 0) { pView = this.findViewById(pid); } View view = null; if (pView != null) { view = pView.findViewById(id); } else { view = this.findViewById(id); } return view; }}
Activity调用
package com.example.basedemo.annotation.diy;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.TextView;import com.example.basedemo.R;public class DIYAnnotationActivity extends AppCompatActivity { @ViewInject(R.id.textView) private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_annotation); ViewUtils.inject(this); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { textView.setText("成功了!"); } }); }}
布局只有一个textview,这里就不罗列布局了。
——————OK,到这一步你已经成功了————————
——————下面为增加版————————
如果上面的还不够过瘾,想添加上点击事件注解,那也没问题。
定义一个onclick声明
package com.example.basedemo.annotation.diy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface OnClick { int[] value(); int[] parentId() default 0;}
然后在ViewUtils里声明多一个方法。这是用了Java的动态代理方法。
public class ViewUtils { ......省略 public static void inject(Activity activity) { injectObject(activity, new ViewFinder(activity)); injectEvent(activity); } ......省略 private static void injectEvent(final Activity activity) { Class<? extends Activity> clazz = activity.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (final Method methodY : methods) { OnClick click = methodY.getAnnotation(OnClick.class); if (click != null) { int[] viewId = click.value(); methodY.setAccessible(true); Object listener = Proxy.newProxyInstance(View.OnClickListener.class.getClassLoader(), new Class[]{View.OnClickListener.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return methodY.invoke(activity, args); } }); try { for (int id : viewId) { View v = activity.findViewById(id); Method setClickListener = v.getClass().getMethod("setOnClickListener", View.OnClickListener.class); setClickListener.invoke(v, listener); } } catch (Exception e) { e.printStackTrace(); } } } } }
在activity里面调用(布局自行添加)
@OnClick(R.id.tb_2) public void onClick(View v) { textView.setText("你按了button2"); }
这时候你又发现你又成功了。
————————————————————
—————来来来,继续升级———————
给setcontentview注解
先设置注解
package com.example.basedemo.annotation.diy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface ContentView { int value();}
然后设置注解处理
public static void injectContentView(Object handler){ Class<?> handlerType = handler.getClass(); // inject ContentView ContentView contentView = handlerType.getAnnotation(ContentView.class); if (contentView != null) { try { Method setContentViewMethod = handlerType.getMethod("setContentView", int.class); setContentViewMethod.invoke(handler, contentView.value()); } catch (Throwable e) { e.printStackTrace(); } } }
activity里面调用
@ContentView(R.layout.activity_annotation)public class DIYAnnotationActivity extends AppCompatActivity { @ViewInject(R.id.textView) private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);// setContentView(R.layout.activity_annotation); ViewUtils.injectContentView(this); ViewUtils.inject(this); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { textView.setText("成功了!"); } }); } @OnClick(R.id.tb_2) public void onClick(View v) { textView.setText("你按了button2"); }}
- Android 自定义注解框架
- Android中的自定义注解
- Android 自定义注解
- Android 自定义注解详解
- Android 自定义注解
- 自定义Android 注解
- Android进阶之自定义注解
- Android ViewUtils注解框架自定义
- Android进阶之自定义注解
- 学习如何自定义Android注解
- Android中的自定义注解(反射实现-运行时注解)
- Android中的自定义注解(反射实现-运行时注解)
- Android中的自定义注解(反射实现-运行时注解)
- Android中的自定义注解(反射实现-运行时注解)
- Android自定义注解与注解器实现点击事件绑定
- Android中的自定义注解(反射实现-运行时注解)
- android 自定义注解 通过反射获取注解属性值
- android自定义注解初始化布局控件(二)
- 深入理解Java虚拟机——JVM垃圾回收机制和垃圾收集器详解
- 9/6 javascript思路梳理。
- 关于是值传递还是引用传递的问题
- 使用NumberPicker遇到的一个坑
- jquery 设置css margin-left
- 自定义Android 注解
- 什么是微店打印机?如何设置自动接单打印?批量打印微店订单
- perf4j+SpringMvc监测代码性能
- C之内存分类
- PDF如何转Word?原生PDF转Word教程
- ssm整合
- 热重启golang服务器(graceful restart golang http server)
- wxPython常用事件
- windows字符和字符串处理