Custom annotation

One case:

Custom ButterKnife implements findViewById and onClick events of the next View with annotations. Custom annotations are generally divided into two steps: the first step is to declare annotations and the second step is to parse annotations.

1. User defined annotation

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 MyBindView {
    int value() default -1 ;
}
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 MyOnClick {
    int[] value() default {-1};
}

2. Custom annotation parser

import android.app.Activity;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyButterKnife {
    public static void init(final Activity activity){
        Class<?> clz = activity.getClass();
        Field[] fields = clz.getDeclaredFields();
        Method[] methods = clz.getDeclaredMethods();
		
		//findViewById
        for(Field field : fields){
            if (field.isAnnotationPresent(MyBindView.class)){
                MyBindView myBindView = field.getAnnotation(MyBindView.class);
                if (myBindView != null){
                    try {
                        field.set(activity, activity.findViewById(myBindView.value()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

		//onClick
        for (final Method method : methods){
            if (method.isAnnotationPresent(MyOnClick.class)){
                MyOnClick onClick = method.getAnnotation(MyOnClick.class);
                if (onClick != null && onClick.value().length > 0){
                    for(int id : onClick.value()){
                        View view = activity.findViewById(id);
                        if (view != null){
                            view.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    try {
                                        method.invoke(activity, view);
                                    } catch (IllegalAccessException e) {
                                        e.printStackTrace();
                                    } catch (InvocationTargetException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                        }
                    }

                }
            }
        }
    }
}

Reflection is used to operate here. After calling the bind method, use CLS getDeclaredFields(); Get all global variables, and then use field for each variable getAnnotation(BindView.class); To get the annotation above this variable. If it exists, int IDS = bindview value(); To get the resources we passed in, and finally call findViewById:

field.set(activity, activity.findViewById(myBindView.value()));

3 use

public class TestActivity extends Activity {

    @MyBindView(R.id.tv)
    TextView textView;

    @MyOnClick(R.id.tv)
    void tvClick(View view){
        Toast.makeText(this, "Click", Toast.LENGTH_LONG).show();
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        MyButterKnife.init(this);

        textView.setText("111111");
    }
}

II. Notes

1 what is annotation

For many first-time developers should have this question? Annotation is a new feature introduced in Java 5. Its Chinese name is annotation. It provides a secure annotation like mechanism to associate any information or metadata with program elements (classes, methods, member variables, etc.). Add more intuitive and clear descriptions to the elements (classes, methods, member variables) of the program. These descriptions are independent of the business logic of the program and are used by the specified tools or frameworks. Like a modifier, annotation is applied to the declaration statements of packages, types, constructors, methods, member variables, parameters and local variables.
Java annotation is some meta information attached to the code, which is used for parsing and using some tools during compilation and running, and plays the function of description and configuration. Annotations do not and cannot affect the actual logic of the code, but only play an auxiliary role. Included in Java Lang.annotation package.

2. Principle of annotation:

Annotation is essentially a special interface that inherits annotation, and its specific implementation class is the dynamic proxy class generated by Java runtime. When we get annotations through reflection, we return the dynamic proxy object $Proxy1 generated by the Java runtime. Calling the method of custom annotation (Interface) through the proxy object will eventually call the invoke method of AnnotationInvocationHandler. This method will retrieve the corresponding value from the Map of memberValues. The source of memberValues is the Java constant pool.

3 function of annotation

Simplify code and improve development efficiency.
Note: it can certainly improve the efficiency of code development, but it does not necessarily provide the efficiency of program operation.

Ternary annotation

Meta annotations are annotations used to define other annotations (when customizing annotations, we need to use meta annotations to define our annotations). java.lang.annotation provides four meta annotations: @ Retention, @ Target, @ Inherited, @ Documented.

Meta annotations are annotations used to modify annotations. We must use meta annotations when customizing annotations. Because we need to define whether we annotate methods or variables, the lifetime of annotations, and so on.


1 @Target
@The Target meta annotation is used to indicate where our annotation can appear. The parameter is an array of ElementType type, so @ Target can set the annotation to appear in multiple places at the same time. For example, it can appear either in front of the class or in front of the variable.
@Target meta annotation ElementType enumeration (used to specify where annotations can appear):

2 @Retention
@Retention indicates the level at which the annotation information needs to be saved, which is used to describe the life cycle of the annotation (that is, to what extent the described annotation is valid). The parameter is the RetentionPolicy enumeration object.
The enumeration types of RetentionPolicy are (the default value is CLASS.):

3 @Document
@Document indicates that the annotations we marked can be documented by tools such as javadoc.

4 @Inherited
@Inherited indicates that the annotation we marked is inherited. For example, if a parent class uses an annotation decorated with @ inherited, the child class is allowed to inherit the annotation of the parent class.

Tags: Java Android

Posted by thessoro on Mon, 16 May 2022 17:14:48 +0300