With it, there is no need to write setContentView anymore! Easy to use, really easy to use~

Preface

Everyone has used or read annotations, such as the most common @Override, @Deprecated, etc. In recent years, some of the more popular three-party frameworks have used annotations, such as ButterKnife (gradually replaced by Databinding and ViewBinding, and has ceased to be maintained), Dagger, Room, and so on. So why are these big cows so keen on using annotations? The reason must be that the benefits of annotations are much greater.

Author

Pig man aoa

Advantages of annotations

  • The inspection of the code exposes some errors before the runtime.
  • Reduce repetitive work and improve work efficiency. For example, ButterKnife, you can reduce our findViewById, set click events, etc.
  • Reduce code coupling. The typical is Dagger.
  • Information configuration, using reflection dynamic processing at runtime.

Meta-annotation (meta-annotation)

What is meta-annotation? It means an annotation defined in the JDK. 4 meta annotations are provided in JDK1.5

@Target

Indicates where the annotation is used, for example, on classes, methods, etc. The detailed scope is as follows:

  • ElementType.TYPE class, interface (including annotation type) or enumeration declaration
  • ElementType.FIELD field declaration
  • ElementType.METHOD method declaration
  • Parameter declaration of ElementType.PARAMETER method
  • ElementType.CONSTRUCTOR class construction method declaration
  • ElementType.LOCAL_VARIABLE local variable declaration
  • ElementType.ANNOTATION_TYPE annotation declaration
  • ElementType.PACKAGE package declaration
  • ElementType.TYPE_PARAMETER JDK1.8 newly added, type parameter declaration
  • ElementType.TYPE_USE JDK1.8 newly added, type use statement

@Retention

Indicates the life cycle of the annotation

  • RetentionPolicy.SOURCE source code stage, will be removed at compile time
  • The RetentionPolicy.CLASS annotation will be saved in the class file and will be removed at runtime
  • The RetentionPolicy.RUNTIME annotation will always exist, and reflection can be used to obtain the corresponding value above the annotation at runtime

@Inherited

Indicates that the subclass is allowed to inherit the annotation type of the parent class

@Documented

Indicates document annotation

Today we are using the features of runtime annotations to do some operations.

Custom annotation

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest {
	int value();
}

The above code customizes an AnnotationTest annotation, @Target is ElementType.TYPE, which means it acts on a class, interface or enumeration. @Retention is RetentionPolicy.RUNTIME, which means it is running. A method with a return value of int is defined internally, which means that an int parameter must be passed when using annotations. Then let's build a class to see how to use it.

@AnnotationTest(1)
public class Test {
}
Test test = new Test();
//获取Test的Class对象
Class<? extends Test> clazz = test.getClass();
//使用Class对象获取对应的注解
AnnotationTest annotation = clazz.getAnnotation(AnnotationTest.class);
if (annotation != null) {
       //获取注解传递的值
       int value = annotation.value();
       Log.d(TAG, "initView: >>>>>>>>>>>" + value);
}

The above code first defines a Test class, and then uses the @AnnotationTest annotation to pass the value 1. Then use reflection to get the annotation of this class, and then get the value passed by the annotation, as shown in the figure above, it is 1.

Then, let’s start to enter our topic today. Use annotations to set the page layout of Activity instead of using setContentView.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
    int value();
}

A ContentView annotation is defined, and the return value is an int type method.

public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        InjectUtils.injectLayout(this);
        initView();
    }

    protected void initView() {

    }
}

A very simple BaseActivity

@ContentView(R.layout.activity_main)
public class MainActivity extends BaseActivity {
}

MainActivity, use ContentView annotations, and then annotations to pass the layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

MainActivity layout

There is also an InjectUtils class, which gets the annotation and layout of MainActivity, and then sets it to MainActivity. The main operation is placed in the InjectUtils class.

public class InjectUtils {
	public static void injectLayout(Object context) {
    	//获取Class对象,这里context就是传递过来的MainActivity
        Class<?> clazz = context.getClass();
        //获取@ContentView注解
        ContentView contentView = clazz.getAnnotation(ContentView.class);
        if (contentView != null) {
        	//获取注解中的布局文件
            int layoutId = contentView.value();
            try {
            	//利用反射调用Activity中的setContentView方法,将布局设置给MainActivity
                Method setContentViewMethod = clazz.getMethod("setContentView", int.class);
                setContentViewMethod.invoke(context, layoutId);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

As shown in the figure above, the layout file has been successfully set to MainActivity. The main operations in the above injectLayout method have been annotated, so I will not explain them one by one here. In fact, in addition to using annotations to set the layout of the Activity, you still use annotations instead of fingViewById, set clicks, and so on. If you need to see using annotations to set controls and click events, you can click here

The point I want to say here is that some students may have pits through reflection acquisition methods (the preparation should be because I don’t use reflection often). I have been pitted for a long time before, but I have stepped on this pit It will make me more memorable and also give me a new understanding of reflection.

The difference between getMethod and getDeclaredMethod

  • getMethod can get the public-modified methods of itself and the parent class
  • getDeclaredMethod can get any of its own methods, the method of the parent class cannot be obtained, even if the method of the parent class is modified with public.

IOC

IOC, short for Inversion of Control, is the inversion of control. What does that mean? IOC is a resource originally acquired actively in the program code. It changes the way of acquiring it by a third party and passively receiving the original code to achieve the effect of decoupling, which is called inversion of control. The most common method is Dependency Injection , or DI for short. Through inversion of control, when an object is created, an external entity that regulates all objects in the system passes (injects) references to the objects it depends on.

My personal understanding is to leave things to others to do, and then just leave the results to me when done. To give a simple example, the boss hired a young and beautiful secretary. The boss wants to work with another company to have dinner, right? The secretary is responsible for booking the hotel and telling the boss after the reservation is made. The partner drank too much, the boss asked the secretary to book the room, and then the secretary told the boss after the room was booked. This is the secret secretary in the biography, it's okay. . .

Dependency injection is a kind of thinking, there is no standard. Just like object-oriented thinking, it is simple and simple. It is too difficult to say it is difficult. If you can appreciate the true meaning of your thoughts, you can't do it overnight. Only through our continuous accumulation, continuous actual combat can it be possible.

to sum up

Today I am mainly talking about annotations, and then use runtime annotations to set the layout, controls, etc. of Activity. Later, I briefly talked about dependency injection, not very detailed. That's it for today, everyone.

End of sentence

Thank you everyone for following me, sharing Android dry goods, and exchanging Android technology.
If you have any insights on the article, or any technical questions, you can leave a message in the comment area to discuss, and I will answer you religiously.
Android architect system advanced learning route, 580,000-word study notes, teaching videos, free sharing address: My GitHub

Guess you like

Origin blog.csdn.net/Androiddddd/article/details/112846913