在前面学习的基础上,我们自己编写一个ViewUtils注解框架类,不清楚的原理看前面的源代码
package im.weiyuan.com.viewutils; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { @ViewInject(R.id.tv_main_title) private TextView tv_main_title; private Button btn_main; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //这里一定要初始化注解 ViewUtils.inject(this); } //login的参数必须是 View view @OnClick(R.id.btn_main) public void login(View view ){ Toast.makeText(MainActivity.this,"事件被点击了",Toast.LENGTH_LONG).show(); } }
package im.weiyuan.com.viewutils; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by wei.yuan on 2017/7/21. */ //指定注解的声明周期 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface OnClick { int value(); }
package im.weiyuan.com.viewutils; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by wei.yuan on 2017/7/21. */ //指定注解的声明周期 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface ViewInject{ int value(); //如果这里定义成id int id();用户在使用的时候必须写成 @ViewInject(id = R.id.tv_main_title),如果定义成int value(); // 用户访问可以写成@ViewInject(R.id.tv_main_title) }
package im.weiyuan.com.viewutils; import android.app.Activity; import android.view.View; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Created by wei.yuan on 2017/7/21. */ public class ViewUtils { public static void inject(Activity activity){ bindView(activity); bindBtn(activity); } /** * 对按钮进行操作 * **/ private static void bindBtn(final Activity activity) { Class clazz = activity.getClass(); /** * 获得所有的方法 * */ Method[] methods = clazz.getDeclaredMethods(); /*** * 多所有的方法进行遍历 * */ for(final Method method:methods){ /** * 看该方法上是否存在注解标签 * */ final OnClick annotation = method.getAnnotation(OnClick.class); if(annotation != null){ /** * 获得注解标签中的值 @OnClick(R.id.btn_main) ,这里的值就是 R.id.btn_main * */ int resId = annotation.value(); /** * 获得该对象 * */ final View btnView = activity.findViewById(resId); /** * 给view 绑定点击监听事件 * */ btnView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { /** * 在点击事件之后执行反射的回调方法 * 匿名内部类访问当前函数的局部变量,局部变量声明为final类型 * */ method.setAccessible(true); try { method.invoke(activity,btnView); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } } } private static void bindView(Activity activity){ //首先获得activity的所有字段,利用反射 Class clazz = activity.getClass(); //获得该字节码中的所有字段信息 Field[] fields = clazz.getDeclaredFields(); //对字段进行遍历,看给那些字段添加了注解的标签 for(Field field :fields){ ViewInject annotation = field.getAnnotation(ViewInject.class); if(annotation != null){ /** * 获得当中注解上的值 * */ int resId = annotation.value(); /** * 通过activity 的findViewById获得当前的控件 * */ View view = activity.findViewById(resId); /** * 通过反射将view的值设置给当前的字段 * */ field.setAccessible(true); /** * 给activity的field字段赋值为view对象 * */ try { field.set(activity,view); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } }
xml文件:
<?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:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="im.weiyuan.com.viewutils.MainActivity"> <TextView android:id="@+id/tv_main_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /> <Button android:text="点击" android:id="@+id/btn_main" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
相当的经典