ButterKnife is an open source IOC framework written by Google’s Jake Wharton. It’s easy to use and saves us a lot of repetitive code. FindViewById: findViewById: findViewById: findViewById: findViewById: findViewById: findViewById: findViewById: findViewById: findViewById

ButterKnife can do many things: bind a View (@bindView); Bind resource (@bindString); Bind listeners (@onclick ()) and so on……… However, I feel that there are only a few frequently used in the project. Today, we will spend five minutes to write one of our own annotations without ButterKnife.

Annotations and reflection go hand in hand, and the implementation of annotations depends on reflection. Create an annotation like ButterKnife’s @bindView: (1) Create a new annotation ViewById

@target (ElementType.FIELD)// Annotation scope :FIELD attribute Public @interface ViewById {//@interface is an annotation int value(); // when @viewById () is annotated, the value inside the parentheses is int}Copy the code

(2) Create a class called ViewBind that implements reflection to create instances of annotated variables.

public class ViewBind {
    public static void inJect(Activity activity) { findViewById(activity); } private static void findViewById(Activity Activity) {// Get the Activity class <? extends Activity> clazz = activity.getClass(); Field[] declaredFields = clazz.getDeclaredFields(); // Iterate through all attributes to find the attributes annotated with @viewByIdfor(int i = 0; i < declaredFields.length; i++) { Field field = declaredFields[i]; // @viewById (r.d.extView) r.D.extView --value // TextView TextView; // Attribute ViewById annotation = field.getannotation (viewByid.class);if(annotation ! = null) { int viewId = annotation.value(); View view = activity.findViewById(viewId); // Private attributes can also be dynamically injected (do not write this sentence, private attributes will raise an exception).true);
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Copy the code

(3) test code: text can be displayed normally, it shows that the mou problem!

public class TestActivity extends AppCompatActivity{
  @ViewById(R.id.textView)
  TextView textView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView (which happens R.l ayout. Act_test); ViewBind.inJect(this); textView.setText("This is annotation test")}}Copy the code

With that in mind, you already know how to write an event-bound annotation: @onClickView

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClickView {
    int[] value(); 
}
Copy the code

Add methods to the previous ViewBind class and call onClick() in the inJect() method

Private static void OnClick (final Activity Activity) {// findViewByIdsetOnClick // 1. Get all of the Activity's methods. > clazz = activity.getClass(); // Method[] methods = clazz.getDeclaredMethods(); // 2. Traverse the method to get all the values //for(final Method Method :methods){// // 2.1 Get OnClick annotation // OnClickView OnClick = method.getannotation (onClickView.class); try { final Method method = clazz.getMethod("onClick", View.class); OnClickView onClick = method.getAnnotation(OnClickView.class); // 2.2 Whether the method has an OnClick annotationif(onClick ! Int [] viewIds = onclick.value (); // @onclick ({r.i.ext_view, r.I.d.button})setOnclick
                for(int viewId: viewIds) {// findViewById final View View = activity.findViewById(viewId); / / after settingsetOnclick
                    view.setOnClickListener(new View.OnClickListener() {@override public void onClick(View v) { Reflection calls method.setaccessible (true); // Private method try {method.invoke(activity); } catch (Exception e) {e.printStackTrace(); try { method.invoke(activity, view); } catch (Exception e1) {e1.printStackTrace(); }}}}); } // } } } catch (NoSuchMethodException e) { e.printStackTrace(); }}Copy the code

Test View click events:

  @OnClickView({R.id.button, R.id.textView})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.textView:
                Toast.makeText(TestActivity.this, "Click on textView", Toast.LENGTH_SHORT).show();
                break;
            case R.id.button:
                Toast.makeText(TestActivity.this, "Click on button", Toast.LENGTH_SHORT).show();
                break; }}Copy the code

Now, bind the View and bind the click event, easy!! Final Demo running results:

ViewBind class complete code:

public class ViewBind {
    public static void inJect(Activity activity) { findById(activity); onClick(activity); Private static void OnClick (final Activity Activity) {// findViewByIdsetOnClick // 1. Get all of the Activity's methods. > clazz = activity.getClass(); // Method[] methods = clazz.getDeclaredMethods(); // 2. Traverse the method to get all the values //for(final Method Method :methods){// // 2.1 Get OnClick annotation // OnClickView OnClick = method.getannotation (onClickView.class); try { final Method method = clazz.getMethod("onClick", View.class); OnClickView onClick = method.getAnnotation(OnClickView.class); // 2.2 Whether the method has an OnClick annotationif(onClick ! Int [] viewIds = onclick.value (); // @onclick ({r.i.ext_view, r.I.d.button})setOnclick
                for(int viewId: viewIds) {// findViewById final View View = activity.findViewById(viewId); / / after settingsetOnclick
                    view.setOnClickListener(new View.OnClickListener() {@override public void onClick(View v) { Reflection calls method.setaccessible (true); // Private method try {method.invoke(activity); } catch (Exception e) {e.printStackTrace(); try { method.invoke(activity, view); } catch (Exception e1) {e1.printStackTrace(); }}}}); } // } } } catch (NoSuchMethodException e) { e.printStackTrace(); }} private static void findById(Activity Activity) {// Get the Activity class <? extends Activity> clazz = activity.getClass(); Field[] declaredFields = clazz.getDeclaredFields();for(int i = 0; i < declaredFields.length; i++) { Field field = declaredFields[i]; // @viewById (r.i.t.extView) r.I.D.extView-value // TextView TextView; // Attribute ViewById annotation = field.getannotation (viewByid.class);if(annotation ! = null) { int viewId = annotation.value(); View view = activity.findViewById(viewId); // Private attributes can also be dynamically injected (do not write this sentence, private attributes will raise an exception).true);
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Copy the code

Now that you’ve read this, do you understand more about annotations? There are a few things you have to know about annotations:

IOC — Inversion of Control. The traditional way of writing a class is to use a number of member variables. To use these member variables, you need to create a new instance. The handling of IOC is: we do not need new, because the coupling degree is too high. You configure an XML file, which indicates which class and which member variables are used in it. When the class is loaded, I will help you to new it. “Writing a configuration file?” you may ask. There is an alternative: add an annotation to the member variable you need to Inject, such as @inject. Reflection will help you create new instances of the variable. That’s it! (reference: https://www.jianshu.com/p/3968ffabdf9d) shallow of IOC framework

The Java reflection mechanism is a running state in which all properties and methods of any class are known. For any object, you can call any of its methods and properties; This ability to dynamically retrieve information and invoke methods on objects is called the Reflection mechanism of the Java language. Function: Which can access to any of a class at run time all properties and methods (2) can create any of a class object at run time (3) can be arbitrary at runtime (4) an object belonging to the class at runtime access to any type of construction method, can create the object (5) at run time for any type of parent or parent interface 6 generate dynamic proxy