Android 认识注解、学习注解、使用注解

1、什么是注解?

就像最常见的 @override注解一样,注解是一种通过一些标注就能自动完成一些代码实现的一种机制。

2、注解的好处

(1)使用注解可以降低项目的耦合度

(2)能自动完成一些代码,实现代码的复用,减轻开发者工作量

(3)代码侵入性较低,使用起来也很方便。

3、什么是元注解?元注解有哪些

元注解是java提供的基础注解,负责注解其他注解。元注解有以下几种

@Retention:注解保留的生命周期 (源码阶段、编译阶段、运行阶段 例如 butternkife 中代替finidviewById 的注解就是编译阶段)

@Target:注解对象的作用范围 对应的是ElementType枚举类里面的值,明确了注解的有效范围,可以同时定义多种target

  • TYPE 类、接口、枚举、注解类型
  • FIELD:类成员(构造方法、方法、成员变量)
  • METHOD:方法
  • PARAMETER:参数
  • CONSTRUCTOR:构造器
  • LOCAL_VARIABLE:局部变量
  • ANNOTATION_TYPE:注解
  • PACKAGE:包声明
  • TYPE_PARAMETER:类型参数
  • TYPE_USE:类型使用声明

@Inherited:注解继承,假设有类A 继承自类B,B类上的注解不会被A继承过去,但是如果B中的注解声明了@Inherited 则就可以被A继承过去,该注解作用范围仅仅是类。

4、应用场景

  • 源码阶段:也是Flutter生成java源码的原理 ,APT技术 在编译期获取注解声明的类、类成员信息,一般用于生成额外的辅助类
  • 字节码阶段:修改字节码文件
  • 运行时阶段:配合反射技术做相应处理

5、自定义注解示例(注解+反射代替 Activity的findViewById工作)

第一步:创建一个自定义注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    //value是默认的,如果只有一个参数,并且名称是value,外面传递时可以直接写值,否则就要通过键值对来传值(例如:value = 1)
//    int value() default 0;
    int id() default 0;
}

第二步:写一个注解处理的工具类BindViewInject

public class BindViewInject {

    /**
     * 注入
     *
     * @param activity
     */
    public static void inject(Activity activity) {
        //第一步 获取class对象
        Class<? extends Activity> aClass = activity.getClass();
        //第二步 获取类本身定义的所有成员变量
        Field[] declaredFields = aClass.getDeclaredFields();
        //第三步 遍历找出有注解的属性
        for (int i = 0; i < declaredFields.length; i++) {
            Field field = declaredFields[i];
            //判断是否用BindView进行注解
            if (field.isAnnotationPresent(BindView.class)) {
                //得到注解对象
                BindView bindView = field.getAnnotation(BindView.class);
                //得到注解对象上的id值 这个就是view的id
                int id = bindView.id();
                if (id <= 0) {
                    Toast.makeText(activity, "请设置正确的id", Toast.LENGTH_LONG).show();
                    return;
                }
                //建立映射关系,找出view
                View view = activity.findViewById(id);
                //修改权限
                field.setAccessible(true);
                //第四步 给属性赋值
                try {
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

第三步:在Activity中使用

public class SecondActivity extends AppCompatActivity {

    @BindView(id = R.id.activity_second_tv)
    private TextView tv;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        BindViewInject.inject(this);
        tv.setText("注入成功");
    }
}

activity_second.xml 布局文件如下

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/activity_second_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Second..."
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

运行截图:

猜你喜欢

转载自blog.csdn.net/u013347784/article/details/109153796
今日推荐