Android development and learning path-Annotation simplifies the experience of the view control at the beginning

Source: Internet
Author: User

Android development and learning path-Annotation simplifies the experience of the view control at the beginning

Generally, when writing an android Activity, we always add the setContentView method to the onCreate method to load layout, and use findViewById to bind the control. Every time we write so many code, we always feel annoyed. Recently, I have read Annotation in android to simplify this process. If I am not familiar with java, I will simply look at it. Springmvc has many annotations when I was playing the web last time. I don't know how to implement them. Basically, this is similar.

The Annotation mainly talks about how to use it here. The simple principle will enclose people. There is no way. The java foundation can only be supplemented later. c has been working for a long time, many object-oriented ideas only stay at the university, except for some object-oriented ideas in the Linux kernel. After talking about so much nonsense, let's continue our study of Annotation. First, we will create a new project, emAnnotationStudy, and EMLayoutBinder. java. The Code is as follows:

package com.jared.emannotationstudy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jared on 16/3/10. */@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface EMLayoutBinder {    int value();}
Here, @ Target, @ Retention, and @ interface are introduced in brief.

@ Target: Specifies the range of objects modified by Annotation. Annotation can be used for classes such as packages and types, interfaces, enumeration, and Annotation. It can also be a class member method, constructor, and member variable, enumerated values, method parameters, and local variables. It generally has the following types:

ElementType. CONSTRUCTOR: CONSTRUCTOR Declaration;

ElementType. FIELD: member variables, objects, and attributes;

ElementType. LOCAL_VARIABLE: local variable Declaration;

ElementType. METHOD: METHOD declaration;

ElementType. PACKAGE: PACKAGE Declaration;

ElementType. PARAMETER: PARAMETER Declaration;

ElementType. TYPE: Class, interface (including annotation TYPE), or enum Declaration;

TYPE is used.

@ Retention: indicates the level at which the annotation information is saved. The general level is as follows:

RetentionPolicy. SOURCE: Stay in the java SOURCE file, and the compiler is discarded.

RetentionPolicy. CLASS: it stays in the class file, but is discarded by the VM.

RetentionPolicy. RUNTIME: Specifies the bytecode in the memory. The VM retains the annotation during RUNTIME. Therefore, the annotation information can be read through the reflection mechanism.

Here we provide the highest level of RUNTIME.

@ Interface: This indicates the annotation. It is similar to interface, but there is an @ symbol added.

Int value (): indicates that the input parameter is of the int type.

Now that the definition is complete, how can we use it? How to develop a single annotation? In fact, annotations are generally used together with java reflection principles. Let's take a simple look at the reflection of java. There are a lot of online materials. Here we will simply understand and understand it. The Reflection mechanism in java is called Reflection. It allows the running java program to check itself and directly operate on the internal attributes or methods of the program.

Reflection APIs can be used to obtain the internal information of any classes with known names, including package, type parameters, superclass, implemented interfaces, inner classes, outer classes, fields constructors, methods, and modifiers.

Class: indicates a specific Class or interface.

Object: Every class uses Object as a superclass. All objects implement the method of this class.

Constructor: encapsulates the Class Constructor

Field: provides information about the attributes of a class or interface and its dynamic access permissions.

Method: Provides information about methods on classes or interfaces.

Modifier: encapsulates the Modifier fields of Class (method, fields.

A Brief Introduction to java's launch mechanism. In fact, reflection is to call some functions of the class in reverse mode, which may be difficult to understand. Let's continue with our study and create the EMAnnotationParser class:

 

package com.jared.emannotationstudy;import android.app.Activity;import android.view.View;import java.lang.reflect.Field;/** * Created by jared on 16/3/10. */public class EMAnnotationParser {    public static void injectActivity(Activity activity) {        if (null == activity) {            return;        }        Class activityClass = (Class) activity.getClass();        if (isEMLayoutBinder(activityClass)) {            EMLayoutBinder layout = activityClass.getAnnotation(EMLayoutBinder.class);            activity.setContentView(layout.value());        }        View decorView = activity.getWindow().getDecorView();    }    private static boolean isEMLayoutBinder(Class
  c) {        return c.isAnnotationPresent(EMLayoutBinder.class);    }

The injectActivity method is implemented here. Get the class of the current Activity through getClass, view the Annotation through isAnnotationPresent, and then get the Annotation through getAnnotation, the layout passed in the annotation is loaded into the activity through the setContentView method of the activity. Well, let's implement MainActivity:

package com.jared.emannotationstudy;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;@EMLayout(R.layout.activity_main)public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        EMAnnotationParser.injectActivity(this);        //setContentView(R.layout.activity_main);    }}
If setContentView is removed, a @ EMLayout command can be used directly. Is it very convenient? Here, the injectActivity method of EMAnnotationParser is used. In fact, a BaseActivity is defined in a project. The MainActivity is implemented by inheriting the BaseActivity, which looks clearer. Then, implement the BaseActivity:
package com.jared.emannotationstudy;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;/** * Created by jared on 16/3/10. */public class BaseActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        EMAnnotationParser.injectActivity(this);    }}
Then implement MainActivity to inherit BaseActivity:
package com.jared.emannotationstudy;import android.os.Bundle;import android.widget.Button;import android.widget.TextView;@EMLayoutBinder(R.layout.activity_main)public class MainActivity extends BaseActivity {    @EMViewBinder(R.id.hello)    private TextView mHello;    @EMViewBinder(R.id.test1)    private Button mTest1;    @EMViewBinder(R.id.test2)    private Button mTest2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mHello.setText("Hello Annotation!");    }}

There are still no problems after running. Since layout has been annotated, the control can also be annotated. The next step is to implement it. First, create Annotation as EMViewBinder:

package com.jared.emannotationstudy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jared on 16/3/10. */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface EMViewBinder {    int value();}

It is easy to understand here. Like LayoutBinder, target is always lD, because it is a member variable. Next, we simply implement the following reflection:
package com.jared.emannotationstudy;import android.app.Activity;import android.view.View;import java.lang.reflect.Field;/** * Created by jared on 16/3/10. */public class EMAnnotationParser {    public static void injectActivity(Activity activity) {        if (null == activity) {            return;        }        Class activityClass = (Class) activity.getClass();        if (isEMLayoutBinder(activityClass)) {            EMLayoutBinder layout = activityClass.getAnnotation(EMLayoutBinder.class);            activity.setContentView(layout.value());        }        View decorView = activity.getWindow().getDecorView();        initViews(activityClass.getDeclaredFields(), decorView, activity);    }    private static boolean isEMLayoutBinder(Class
  c) {        return c.isAnnotationPresent(EMLayoutBinder.class);    }    private static boolean isEMViewBinder(Field filed) {        return filed.isAnnotationPresent(EMViewBinder.class);    }    private static void initViews(Field[] fields, View view, Object object) {        View view1;        for (Field field : fields) {            if(isEMViewBinder(field)) {                EMViewBinder emView = field.getAnnotation(EMViewBinder.class);                view1 = view.findViewById(emView.value());                if(null != view1) {                    try {                        field.setAccessible(true);                        field.set(object, view1);                    } catch (IllegalAccessException e) {                        e.printStackTrace();                    } catch (IllegalArgumentException e) {                        e.printStackTrace();                    }                }            }        }    }}

GetDecorView is used to obtain the view, getDeclaredFields is used to obtain the Fields, getAnnotation is used to obtain the EMViewBinder annotation, and findViewById is called to find the control. If it is found, you need to call setAccessible to true, because the variables are generally private. The general meaning is as follows. Let's modify layout:
<!--{cke_protected}{C}%3C!%2D%2D%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%2D%2D%3E--><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" android:layout_margin="10dp" tools:context="com.jared.emannotationstudy.MainActivity">    <textview android:id="@+id/hello" android:text="Hello World!" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textsize="20sp" android:layout_gravity="center"><button android:id="@+id/test1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test1" android:textallcaps="false"></button><button android:id="@+id/test2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test2" android:textallcaps="false"></button></textview></linearlayout>
Then we add the code in MainActivity as follows:
package com.jared.emannotationstudy;import android.os.Bundle;import android.widget.Button;import android.widget.TextView;@EMLayoutBinder(R.layout.activity_main)public class MainActivity extends BaseActivity {    @EMViewBinder(R.id.hello)    private TextView mHello;    @EMViewBinder(R.id.test1)    private Button mTest1;    @EMViewBinder(R.id.test2)    private Button mTest2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mHello.setText("Hello Annotation!");    }}
The running result is as follows:

It has fully met our expectations and is very convenient to write code. We don't need to introduce a lot of findviewbyids. You can easily add more widgets. Now that the control is bound, you need to bind the event. Here we mainly implement button events and create EMOnClickBinder:

package com.jared.emannotationstudy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by jared on 16/3/10. */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface EMOnClickBinder {    int[] value();}
The METHOD is implemented here, so the METHOD is used, and there may be many buttons, so the int [] array is used. Then we implement the specific reflection:
private static boolean isEMOnClickBinder(Method method) {        return method.isAnnotationPresent(EMOnClickBinder.class);    }    private static void initOnClick(Method[] allMethod, View root, Object object) {        for (Method method : allMethod) {            if (isEMOnClickBinder(method)) {                EMOnClickBinder onClick = method.getAnnotation(EMOnClickBinder.class);                MyOnClickListener click = new MyOnClickListener(method, object);                int[] ids = onClick.value();                for (int id : ids) {                    root.findViewById(id).setOnClickListener(click);                }            }        }    }    static class MyOnClickListener implements View.OnClickListener {        private Method mMethod;        private Object mReceiver;        public MyOnClickListener(Method method, Object receiver) {            mMethod = method;            mReceiver = receiver;        }        @Override        public void onClick(View v) {            try {                mMethod.setAccessible(true);                mMethod.invoke(mReceiver, v);            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (IllegalArgumentException e) {                e.printStackTrace();            } catch (InvocationTargetException e) {                e.printStackTrace();            }        }    }
Here we use ID Search, call the setOnClickListener method to register the method, and use MyOnClickListener to perform specific operations. When an event is triggered, The onClick method is called and the method invoke method is called. The user-defined method under the annotation is called, and the View is passed in here. The specific MainActivity implementation is as follows:
package com.jared.emannotationstudy;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;@EMLayoutBinder(R.layout.activity_main)public class MainActivity extends BaseActivity {    @EMViewBinder(R.id.hello)    private TextView mHello;    @EMViewBinder(R.id.test1)    private Button mTest1;    @EMViewBinder(R.id.test2)    private Button mTest2;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mHello.setText("Hello Annotation!");    }    @EMOnClickBinder({R.id.test1, R.id.test2})    public void myOnClick(View view) {        switch (view.getId()) {            case R.id.test1:                mHello.setText("I am test1");                break;            case R.id.test2:                mHello.setText("I am test2");            default:                break;        }    }}
Is it very simple and clear? In the future, using these files as tools and simple encapsulation, you don't need to write so many findViewById and setOnClickListener each time. Basically, Annotation will be learned here first.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.