Android 注解

干了蛮久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



------今天简单了解了一下,还有很多不会懂的,年后继续研究了----


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值