干了蛮久Android 用过注解但是没研究过,是挺土的。适逢过年前没有工作热情,索性放下手里的工作,在工位上学习一下。
在我简单总结了一下,使用自定义注解,有几个步骤
1.定义注解类
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by bxh on 1/24/17.
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
int value() default 0;
}
2.定义绑定注解的工具类
public class InjectUtils {
public static void autoInjectAllField(Activity context) {
try {
Class<?> clazz = context.getClass();
Field[] fields = clazz.getDeclaredFields();//获得Activity中声明的字段
for (Field field : fields) {
// 查看这个字段是否有我们自定义的注解类标志的
if (field.isAnnotationPresent(ViewInject.class)) {
ViewInject inject = field.getAnnotation(ViewInject.class);
int id = inject.value();//此处的‘value()’ ViewInject.java中方法名字一致即可
if (id > 0) {
field.setAccessible(true);
field.set(context, context.findViewById(id));//给我们要找的字段设置值
}
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
3.在代码中使用
package com.example.bxh.sayhello;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
import com.example.bxh.sayhello.inject.InjectUtils;
import com.example.bxh.sayhello.inject.ViewInject;
public class MainActivity extends Activity {
@ViewInject(R.id.text)
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InjectUtils.autoInjectAllField(this);//注意调用位置,在setContentView之后
handler.sendEmptyMessageDelayed(1,2000);
}
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mTextView.setText("hahaahhahahahahahahahaha");
}
};
}
-----------------------------------------
需要弄清楚几个问题:
1.RetentionPolicy是什么?
2.ElementType是什么?
3.是不是还有其他的‘字段’,都是什么?
ps:修饰注解的注解,叫做‘元注解’
关于RetentionPolicy,源码如下:
/**
* Annotation retention policy. The constants of this enumerated type
* describe the various policies for retaining annotations. They are used
* in conjunction with the {@link Retention} meta-annotation type to specify
* how long annotations are to be retained.
*
* @author Joshua Bloch
* @since 1.5
*/
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
,查了一下别人的blog(http://www.cnblogs.com/Fndroid/p/5354644.html),解释如下:
- SOURCE作为最弱的一种策略,被标注为RetentionPolicy.SOURCE的注解,只是作为写码时的一种提醒,告诉我们某个特殊的含义,就像Android Studio中关键字、类名或者方法名的颜色区分,编译器并不会读取它。比如@Override注解,只是为了表明该方法是从父类中重写的,即便我们注释掉该注解,也不影响程序的编译和运行。
- CLASS是缺省的保持策略,被标注为RetentionPolicy.CLASS的注解会影响到编译过程,但不影响到运行时。比如@TargetApi,可以用他来屏蔽掉编译时的非法版本API的错误,但是,如果你并没有在该注解标注的代码段内处理好新老版本的API使用问题的话,程序还是会在运行时发生异常。
- RUNTIME作为权限最高的策略,其保持策略会持续到运行时,因此可以使用反射来在运行时检测注解的存在与否。
关于ElementType,定义如下:
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
* @hide 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
* @hide 1.8
*/
TYPE_USE
}
上面这个类是用来约定注解的使用目标,比如前面用了FIELD,还有用于方法的,具体解释如下:
TYPE,// 类、接口、注解类型或枚举
FIELD, //属性
METHOD, //方法
PARAMETER,// 用于描述参数
CONSTRUCTOR,//构造方法
LOCAL_VARIABLE,//局部变量
ANNOTATION_TYPE,//注解类
PACKAGE //包
ps:目前为止我只看过几种类型的使用
关于还有什么其他的 注解修饰符,在对应的包下面找到这些类:
1.使用注解,定义了default 值得话,是不需要在使用时赋值的
@ViewInject()不会报错的,只是后面mTextView 为null
2.如果注解类中某个方法没有指定default值,那么使用的时候必须制定其值
例如,在ViewInject.java里面加上 int value3() ; 那么在使用时仅仅写成@ViewInject(R.id.test) 会在编译的时候报错:
“Error:(14, 5) error: annotation @ViewInject is missing a default value for the element 'value3'”
要这样用:@ViewInject(value = R.id.text,value3 = 0)
3.发现仅有一个方法的时候,@ViewInject(R.id.text) 和 @ViewInject(value = R.id.text) 等价
4.Android中其他的注解 https://developer.android.com/studio/write/annotations.html
------今天简单了解了一下,还有很多不会懂的,年后继续研究了----