使用反射+注解,教你学会最简单的依赖注入
2017-03-02 16:16
483 查看
本文意于让人简单地使用注解+反射,用注解让控件实现findViewById()以及setOnClickListener(),不再重复写findViewById这些重复性的代码。
网上已经有很多这种框架,比如xUtils,Butterknife等,浅略地看了这两个框架的源码,前者使用的是注解和反射的方式,后者使用的是编译期生成一些代码,可以看Android Studio中的app/build/generated/source/apt,这里都是编译后,框架自动生成的代码。而这两种均能实现这些功能。区别在于,前者使用的是注解+反射,可能会一定程度影响性能,但是,在这个手机性能过剩的时代,这种影响真的可以忽略了。而后者可能在编译期会消耗一些性能,但是运行的时候不会有影响。
以上,均是个人理解。如有不同意见,可以留言一起探讨一下。
一、首先先看一个炒鸡简陋的界面。
因为只是为了能使用,就没有弄一些比较花哨的界面,只要功能实现了就好了。
打开这个界面的时候,在onStart()生命周期打印了按钮1的文本,证明此时按钮1已经是绑定成功了。
接下来是点击按钮二,只是简单的吐司一下。
这就是要讲的全部了,主要不在于界面,而是怎么去实现这个。
二、自定义注解。
关于Java的注解,网上的教程很多,在这里不再论述了,而且讲得不好倒坏了事了。
首先是控件绑定的注解类(就是代替findViewById()方法的注解)
关于这个注解类的说明,注释我觉得已经讲清楚了。如果还不清楚的话,Google(百度也行)吧。
这个注解的使用是
这样就是绑定一个Button控件了。
接下来就是控件点击事件的注解类(就是setOnClickListener()方法的注解)
使用方法
三、控件的绑定与事件的绑定
完成注解类之后,接下来就是控件的各种绑定操作了。
首先,需要进行控件绑定的话,需要在Activity的onCreate()方法中调
4000
用一个用于绑定操作的方法
绑定的操作是在InjectUtils类中执行的,调用的jnject()方法
在这个方法里调用了两个方法,分别是绑定控件跟绑定事件。
先来看控件的绑定
该方法的整体思路是:
1、获取到这个Activity中所有的成员字段(Field)
2、然后遍历每个字段,看是否有对应的 ViewInject 这个自定义注解存在。
3、如果存在这个注解,获取到这个注解里面的值(控件id),并根据该值找到当前的控件(View)。
4、将这个View跟Activity绑定。
这样就完成了Activity上所有带自定义注解(ViewInject)的控件的绑定。
点击事件的绑定
思路:
1、找到所有的方法。
2、遍历方法,看是否有自定义注解(OnClick)存在。
3、存在这个注解,获取到注解里面的值,找到对应的控件(View)。
4、调用这个View的setOnClickListener()方法,在这个监听方法里面调用Activity中有@OnClick注解的方法,这样就实现了点击事件的转换。
(注:直接在这里调用setOnClickListener()只是为了可以更清楚的理解,真正要做得更好是不会这么写死的。可能会用动态代理来实现。)
以上就完成了控件的绑定跟点击事件的绑定。
四、最后再瞄一眼ManActivity
这样就完成了一个很简单的依赖注入迷你框架了(请让我装下逼假装说是个框架,勿喷!)。
本文源码
网上已经有很多这种框架,比如xUtils,Butterknife等,浅略地看了这两个框架的源码,前者使用的是注解和反射的方式,后者使用的是编译期生成一些代码,可以看Android Studio中的app/build/generated/source/apt,这里都是编译后,框架自动生成的代码。而这两种均能实现这些功能。区别在于,前者使用的是注解+反射,可能会一定程度影响性能,但是,在这个手机性能过剩的时代,这种影响真的可以忽略了。而后者可能在编译期会消耗一些性能,但是运行的时候不会有影响。
以上,均是个人理解。如有不同意见,可以留言一起探讨一下。
一、首先先看一个炒鸡简陋的界面。
因为只是为了能使用,就没有弄一些比较花哨的界面,只要功能实现了就好了。
打开这个界面的时候,在onStart()生命周期打印了按钮1的文本,证明此时按钮1已经是绑定成功了。
接下来是点击按钮二,只是简单的吐司一下。
这就是要讲的全部了,主要不在于界面,而是怎么去实现这个。
二、自定义注解。
关于Java的注解,网上的教程很多,在这里不再论述了,而且讲得不好倒坏了事了。
首先是控件绑定的注解类(就是代替findViewById()方法的注解)
/** * 描述:用于注解成员的注解类 * 包名:xiedroid.didemo.utils * 类名:ViewInject * * @author XieQingXiong */ @Target(ElementType.FIELD)//标识这个注解类只能注解字段 @Retention(RetentionPolicy.RUNTIME) //表示这个注解在运行时期起作用 public @interface ViewInject { // 注解里面的值,为 int 类型,用value表示是默认的 // 比如:使用这个注解的时候 // @ViewInject(R.id.btn1),R.id.btn1是int值,可以不用 @ViewInject(value=R.id.btn1)的形式。 // 如果不是 int value() ,而是 int name() 的话,则使用注解时就要用 @ViewInject(name=R.id.btn1) // 所以说 value是一个默认的值 int value(); }
关于这个注解类的说明,注释我觉得已经讲清楚了。如果还不清楚的话,Google(百度也行)吧。
这个注解的使用是
@ViewInject(R.id.btn1) private Button btn1;
这样就是绑定一个Button控件了。
接下来就是控件点击事件的注解类(就是setOnClickListener()方法的注解)
/** * 描述:点击事件的注解类 * 包名:xiedroid.didemo.utils * 类名:OnClick * * @author XieQingXiong */ @Target(ElementType.METHOD)//只能使用方法上 @Retention(RetentionPolicy.RUNTIME)//运行期起作用作用 public @interface OnClick { int value(); }
使用方法
@OnClick(R.id.btn2) public void btn2Click(View v){ //处理逻辑 }
三、控件的绑定与事件的绑定
完成注解类之后,接下来就是控件的各种绑定操作了。
首先,需要进行控件绑定的话,需要在Activity的onCreate()方法中调
4000
用一个用于绑定操作的方法
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InjectUtils.inject(this); }
绑定的操作是在InjectUtils类中执行的,调用的jnject()方法
public static void inject(Activity activity) { //绑定控件 bindView(activity); //点击事件的绑定 bindEvent(activity); }
在这个方法里调用了两个方法,分别是绑定控件跟绑定事件。
先来看控件的绑定
private static void bindView(Activity activity) { //获取class Class<? extends Activity> clazz = activity.getClass(); //获取到这个类的所有的成员字段 Field[] declaredFields = clazz.getDeclaredFields(); //遍历所有的字段 for (int i = 0; i < declaredFields.length; i++) { //判断这个成员字段中有没有ViewInject这个注解 ViewInject viewInject = declaredFields[i].getAnnotation(ViewInject.class); //如果没有这个注解,跳过这个成员字段 if (viewInject == null) continue; //获取注解的值,在这里就是控件的id int resId = viewInject.value(); //得到这个控件 View view = activity.findViewById(resId); try { //暴力反射,如果不设置这个,那么如果成员是private的话,就不能进行绑定 declaredFields[i].setAccessible(true); //将这个控件跟activity绑定 declaredFields[i].set(activity,view); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
该方法的整体思路是:
1、获取到这个Activity中所有的成员字段(Field)
2、然后遍历每个字段,看是否有对应的 ViewInject 这个自定义注解存在。
3、如果存在这个注解,获取到这个注解里面的值(控件id),并根据该值找到当前的控件(View)。
4、将这个View跟Activity绑定。
这样就完成了Activity上所有带自定义注解(ViewInject)的控件的绑定。
点击事件的绑定
private static void bindEvent(final Activity activity) { Class<? extends Activity> clazz = activity.getClass(); //获取所有的方法 Method[] declaredMethods = clazz.getDeclaredMethods(); for (final Method method : declaredMethods) { //获取方法上的OnClick注解 OnClick onClick = method.getAnnotation(OnClick.class); if (onClick == null) continue; //获取控件的id int resId = onClick.value(); final View view = activity.findViewById(resId); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { //暴力反射 method.setAccessible(true); method.invoke(activity,view); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }); } }
思路:
1、找到所有的方法。
2、遍历方法,看是否有自定义注解(OnClick)存在。
3、存在这个注解,获取到注解里面的值,找到对应的控件(View)。
4、调用这个View的setOnClickListener()方法,在这个监听方法里面调用Activity中有@OnClick注解的方法,这样就实现了点击事件的转换。
(注:直接在这里调用setOnClickListener()只是为了可以更清楚的理解,真正要做得更好是不会这么写死的。可能会用动态代理来实现。)
以上就完成了控件的绑定跟点击事件的绑定。
四、最后再瞄一眼ManActivity
public class MainActivity extends AppCompatActivity {
@ViewInject(R.id.btn1) private Button btn1;
@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InjectUtils.inject(this); }
@Override
protected void onStart() {
super.onStart();
Log.e("xqx", "onStart: 得到按钮的名字 === "+btn1.getText().toString());
}
@OnClick(R.id.btn2)
public void btn2Click(View v){
Toast.makeText(this, "点击了按钮2", Toast.LENGTH_SHORT).show();
}
}
这样就完成了一个很简单的依赖注入迷你框架了(请让我装下逼假装说是个框架,勿喷!)。
本文源码
相关文章推荐
- 依赖注入 - 如何使用反射和注解实现简单的依赖注入
- PHP实现依赖注入-使用反射机制和动态代理技术 - 简单思想(咋个办呢 zgbn)
- spring 框架中的依赖注入(IOC--设值注入)--使用注解--的具体实例的简单实现
- 依赖注入框架Autofac的简单使用
- Spring依赖注入的简单示例(基于注解配置)
- 利用反射实现简单的Spring注解注入实例
- asp.net mvc4 简单使用Autofac依赖注入小结
- 有关spring的依赖注入和@resource注解的使用
- 依赖注入之Android RoboGuice简单使用
- 依赖注入框架Autofac的简单使用
- 依赖注入框架Autofac的简单使用
- Ioc容器-Autofac 之四-依赖注入框架Autofac的简单使用
- 依赖注入框架Autofac的简单使用
- 依赖注入框架Autofac的简单使用
- 依赖注入框架Autofac的简单使用
- Java反射及依赖注入简单模拟
- day01-spring2.5.5中使用“依赖注入的注解”
- android使用篇(四) 注解依赖注入IOC实现绑定控件
- 使用反射及依赖注入实现灵活的插件模式
- Java反射及依赖注入简单模拟