preface

Hello, I’m Pig Man. You’ve all used or seen annotations at some point, such as @override, @deprecated, and so on. Annotations used by some of the more popular tripartite frameworks in recent years, such as ButterKnife (gradually replaced by Databinding, ViewBinding, no longer maintained), Dagger, Room, etc. So why are these great people so keen on annotations? The reason must be that annotations are so much better.

Advantages of annotations

  • A review of the code exposes some errors before run time.
  • Reduce repetitive work and improve work efficiency. ButterKnife, for example, can reduce our findViewById, set click events, and more.
  • Reduce the coupling of code. Dagger is typical.
  • Information configuration, dynamic processing at run time using reflection.

Meta-annotations

Meta annotations are defined in the JDK. Four meta-annotations are provided in JDK1.5

@Target

Indicates where the annotation is used, e.g. on a class, method, etc.

  • Elementtype. TYPE class, interface (including annotation TYPE), or enumeration declaration
  • Elementtype. FIELD FIELD declaration
  • Elementtype. METHOD METHOD declaration
  • PARAMETER PARAMETER declaration of the elementType. PARAMETER method
  • CONSTRUCTOR declaration of the ElementType.CONSTRUCTOR class
  • Elementtype. LOCAL_VARIABLE Local variable declaration
  • ElementType.ANNOTATION_TYPE Annotation declaration
  • ElementType. PACKAGE PACKAGE declaration
  • Elementtype. TYPE_PARAMETER Specifies a new type parameter in JDK1.8
  • Elementtype. TYPE_USE new in JDK1.8, using type declarations

@Retention

Represents the life cycle of the annotation

  • Retentionpolicy. SOURCE SOURCE phase, removed at compile time
  • The retentionPolicy.class annotation is saved in the CLASS file and removed at run time
  • The retentionPolicy. RUNTIME annotation is always there, and reflection can be used at RUNTIME to retrieve the corresponding value on the annotation

@Inherited

Represents an annotation type that allows subclasses to inherit from their parent

@Documented

Presentation of document annotations

Today we are going to take advantage of the runtime annotation feature to do some tricks.

Custom annotations

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

The code above defines a custom AnnotationTest annotation, @target being elementType. TYPE, for classes, interfaces, or enumerations. @Retention is RetentionPolicy.RUNTIME, which means in RUNTIME. Internally we define a method that returns an int, indicating that we pass an int when using an annotation. So let’s create a class to see how it works.

@AnnotationTest(1)
public class Test {
}
Copy the code
Test test = new Test(); // Get the Test Class<? extends Test> clazz = test.getClass(); AnnotationTest annotation = clazz.getannotation (annotationtest.class); if (annotation ! Int value = annotate.value (); Log.d(TAG, "initView: >>>>>>>>>>>" + value); }Copy the code

This code first defines a Test class, then passes the value 1 using the @annotationTest annotation. Reflection is then used to get the annotation for that class, and then the value passed by the annotation, as printed out above, is 1.

Let’s move on to the topic of today, using annotations to set the Activity’s page layout instead of using setContentView.

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

Defines a ContentView annotation that returns a method of type int.

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

    protected void initView() {

    }
}
Copy the code

A very simple BaseActivity

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

MainActivity uses the ContentView annotation, which then passes the layout

<? The 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>Copy the code

The layout of the MainActivity

There is also an InjectUtils class that takes the annotations and layout of the MainActivity and then sets them to the MainActivity. The main action is to put them in the InjectUtils class.

Public class InjectUtils {public static void injectLayout(Object Context) { So the context is the MainActivity Class<? > clazz = context.getClass(); // Get @contentView annotation ContentView ContentView = clazz.getannotation (contentView.class); if (contentView ! Int layoutId = contentView.value(); // Call the Activity setContentView method with reflection, Set the layout to MainActivity Method setContentViewMethod = clazz.getMethod("setContentView", int.class); setContentViewMethod.invoke(context, layoutId); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); }}}}Copy the code

So, you’ve successfully set the layout file to MainActivity. The main operations in the injectLayout method above have been commented out, which I won’t explain here. Instead of using annotations to set the layout of the Activity, use annotations instead of fingViewById, setting clicks, and so on. To see how to use annotations to set controls and click events, click here

Here I would like to say that the method of reflection for some students may exist pit (prepared to say that I do not often use the reason of reflection), I have been this pit for a long time, but after stepping on this pit will make me more profound memory, but also let me have a new understanding of reflection.

GetMethod and getDeclaredMethod

  • GetMethod can get its own and its parent’s publicly decorated methods
  • GetDeclaredMethod getDeclaredMethod getDeclaredMethod getDeclaredMethod getDeclaredMethod getDeclaredMethod getDeclaredMethod getDeclaredMethod

IOC

IOC: Inversion of Control. What does that mean? IOC is the resource that was originally acquired actively by the program code. To achieve the decoupling effect by changing the way that the original code is passively received and obtained by a third party, it is called inversion of control. The most common approach is Dependency Injection, or DI. With inversion of control, when an object is created, it is passed (injected) a reference to the object on which it depends by an external entity that regulates all objects in the system.

My personal understanding is to leave the work to others, and then leave the results to me. Let’s take a simple example. The boss hires a young and beautiful secretary. The boss is going to cooperate with another company to have dinner, right? The secretary is responsible for booking the hotel, and then tell the boss. The partner drank too much, the boss asked the secretary to book a room, and then the secretary booked a room and told the boss. That’s what it’s all about.

Dependency injection is an idea, there are no standards. Like object oriented thinking, it’s simple to say. It’s hard to say it’s hard. To be able to appreciate the true meaning of thought, that is not a day to do time. Only through our continuous accumulation, continuous combat is possible to achieve.

conclusion

Today we’re going to focus on annotations, and then we’re going to use runtime annotations to set up Acivity layouts, controls, etc. Then I talked briefly about dependency injection, not in great detail. That’s all for today. Come on.