Android 注解 (Annotation)

      本文是应用在Android环境上的,示例也以Android示例为主;其次,Android先在已经有了官方AnnotationProcessor编译时解析实现,已继承在API中,由于它是编译时执行,固然不会出现反射中的性能消耗; 该文中示例采用比较彻底的注解完成了咱们平时使用的activity中  引入layout布局和findViewById方法 的使用

反射还不太了解的童鞋,你可以先了解以下 java反射

 

一、什么是注解

      注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释;

java元注解:(元注解,简单理解,就是注解上的注解)

@Override                  它的作用是对覆盖超类中方法的方法进行标记
@Deprecated             它的作用是对不应该再使用的方法添加注解
@SuppressWarnings 它的作用是对当前方法或字段异常时的警告

二、简单使用注解

2.1 了解JDK1.5后加的内部注解

//基类
public abstract class Base {

	public abstract void one();
	
	@Deprecated     //表示该方法为过时方法,过时不再支持使用
	public void two(){};
 
}

//继承
public class Base2 extends Base {

	@SuppressWarnings("deprecation")
	@Override //表示该方法时继承父类的方法
	public void one() {
         //当调备注"过时"标签时,系统会提示有警报,然后调用SuppressWarnings可以取消工具上的报警状态
	 super.two(); 
        }  
}

 下图为没加SuppressWarnings标签的样子

 

2.2 自定义注解的简单使用

package annot;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解
 * @author mwt 
 * 
 * 注意了,自定义注解的标志是“@interface”,要和接口interface区分开噢
 */

//如下代码,示例中的@Retention指定了什么时候加载注解类,RetentionPolicy.RUNTIME为运行时
@Retention(RetentionPolicy.RUNTIME)

//@Target指定当前注解可以加在哪些地方,案例中就是加载到类和方法
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Test1 {

	//default 表示整型id默认值为123
	public int id() default 123; 
	// 字符串类型
	public String message() default "默认值";
	
}


//-----------------------注解使用-------------------------------

package annot;

/**
 * 对自定义注解的使用
 * @author mwt 
 */
@Test1(message="自定义注解开始使用了") //改变单个属性值
public class TestUse {

	public static void main(String[] args) { 
		
		//改行代码是用来判断当前 “TestUse”类是否加了Test1注解
		boolean hasAnnotation = TestUse.class.isAnnotationPresent(Test1.class);
		//经过判断如果加了注解,则进入下一步
        if (hasAnnotation) {
        	//该行代码是用来获取当前注解
        	Test1 testAnnotation = TestUse.class.getAnnotation(Test1.class);
        	//获取当前注解中的属性
            System.out.println("value:"+testAnnotation.id()+"  \nmessage"+testAnnotation.message()); 
          }
        }

}


//----------------日志输出

value:123  
message自定义注解开始使用了

 

三、在Android中简单使用注解(基于反射)

3.1 首先我们先完成两个自定义注解;分别是对layout和view的注解

package cn.annto;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解 - layout
 * Created by mwt on 2018/9/26.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface LayoutBind {

    //当只有一个属性的时候,可以使用value来表示,在使用时可以省略掉key和=
    public int value();
}


//---------------------------view 注解----------------------

package cn.annto;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解 -
 * Created by mwt on 2018/9/26.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
public @interface ViewBind {

    //当只有一个属性的时候,可以使用value来表示,在使用时可以省略掉key和=
    public int value();
}

3.2 写一个解读activity中注解的工具类

 

package cn.annto;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import java.lang.reflect.Field;

/**
 * Created by mwt on 2018/9/26.
 * 为什么要写成抽象类呢,因为我可以强制性继承类重写该方法
 */

public abstract class ActivityUntil extends AppCompatActivity {

    private int layoutId;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initLayout();
        initView();
        doWrok();
    }

    protected abstract void doWrok();

    /**
     * 该方法主要就是从注解中获取到注解入的值
     */
    private void initLayout() {
        //首先判断一下是否属于当前注解的子类 ;如果是提供给别人使用的话,务必要有判空操作
        boolean isannotation = this.getClass().isAnnotationPresent(LayoutBind.class);
        if (isannotation){
            //获取当前的注解
            LayoutBind annotation = getClass().getAnnotation(LayoutBind.class);
            //获取注解中的值,并将该值赋给全局变量layoutid,然后供setContentView使用
            layoutId = annotation.value();
            //吧layout布局引入
            setContentView(layoutId);
        }
    }

    /**
     * 初始化activity中生命的字段
     */
    private void initView() {
        //获取当前class对象
        Class<? extends ActivityUntil> aClass = this.getClass();
        //获取到该class中自定义的所有字段
        Field[] declaredFields = aClass.getDeclaredFields();
        //便利所有的字段
        for (Field field: declaredFields) {
            //所有的字段便利出来了,但是我们只需要那些被加过注解的字段
            if(null != field.getAnnotations() && field.isAnnotationPresent(ViewBind.class)){
                field.setAccessible(true);//所有字段都可访问修改
                //获取字段上的注解类
                ViewBind viewBind = field.getAnnotation(ViewBind.class);
                //获取该字段通过注解注入  值,也就是 R.id.textview .....
                int viewid = viewBind.value();
                //现在字段获取到了,对应view 的id也获取到了,那就应该赋值了
                try {
                    field.set(this,findViewById(viewid));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    Log.e("error","not find view id");
                }
            }
        }
    }
}

3.3 自定义注解和解读工具类都具备了,让我们来使用一把吧

package cn.annto;

import android.widget.TextView;

@LayoutBind(R.layout.activity_main)
public class MainActivity extends ActivityUntil {

    @ViewBind(R.id.one)
    public TextView oneText;
    @ViewBind(R.id.two)
    public TextView twoText;


    @Override
    protected void doWrok() {
        oneText.setText("注解测试");
        twoText.setText("注解通过了");
    }
}

运行效果:

本文中第三节Android demo 在github上有完整示例,https://github.com/mawantong/annto/tree/master

 

      

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值