注入框架实践,简单实现一个类似于butterknife的注入框架



这几年针对Android推出了不少View注入框架,例如ButterKnife。我们首先来了解一下使用这些框架有什么好处,其实好处很明显:它可以减少大量的findViewById以及setOnClickListener代码,简化了代码,让我们的代码看起来条理更清晰,可读性变强。

可能大多数对于这一类框架,都只是停留在用的阶段,但是作为一个程序员,我们有必要去了解它是如何实现的。其实它的原理也没有多复杂,用到了java中反射和注解的相关知识,所以对反射和注解了解不多的朋友可以先找一下相关资料了解一下。

关于注解,我推荐一篇文章(简单易懂)http://mp.weixin.qq.com/s/NwlIy_knmx4Es7kFnk0gRQ

今天的任务呢就是教大家如何一步一步简单的实现一个类似 ButterKnife的依赖注入的效果:

第一步:我们需要自定义注解,如下:

//用于初始化view的

    @Target(ElementType.FIELD)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface BindView {  
        int value() default 0;  
    }  


//用于绑定点击事件的

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface BindClick {  
        int value() default 0;  
    }  

从上面的Target里面的值我们可以知道,这两个注解一个是作用于属性,一个是作用于方法的。这里提醒一下,如果如果只有一个参数成员,最好把参数名称设为value,这里可以补一句因为使用该注解时,value作为key可省略,在使用的时候比较方便。
第二步:设置注解

    @BindView(R.id.button)  
    private Button mButton;  
    @BindView(R.id.textview)  
    private TextView mTextView;




点击事件的绑定


    @BindClick(R.id.button)  
    private void onButtonClick(){  
        Toast.makeText(this,"Button被点击了",Toast.LENGTH_SHORT).show();  
    }  
    @BindClick(R.id.textview)  
    private void onTextViewClick(){  
        Toast.makeText(this,"TextView被点击了",Toast.LENGTH_SHORT).show();  
    }  

第三步:获取注解,进行处理

    public class InjectUtils {  
        public static void inject(final Activity activity) {  
            //遍历属性,对设置注解的view进行初始化  
            Class<Activity> activityClass= (Class<Activity>) activity.getClass();  
            Field fields[]=activityClass.getDeclaredFields();  
            for(Field field:fields){  
                if(field.isAnnotationPresent(BindView.class)){  
                    int viewId=field.getAnnotation(BindView.class).value();  
                    View view=activity.findViewById(viewId);  
                    try {  
                        //这一行代码是必须的,否则直接调用set方法不生效  
                        field.setAccessible(true);  
                        field.set(activity,view);  
                    } catch (IllegalAccessException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
            //遍历方法 将设置注解的方法绑定到相应的view的点击事件中  
            Method methods[]=activityClass.getDeclaredMethods();  
            for(final Method method:methods){  
                BindClick bindClick=method.getAnnotation(BindClick.class);  
                if(bindClick!=null){  
                    int viewId=bindClick.value();  
                    activity.findViewById(viewId).setOnClickListener(new View.OnClickListener() {  
                        @Override  
                        public void onClick(View view) {  
                            try {  
                                //调用该方法  
                                method.setAccessible(true);  
                                method.invoke(activity);  
                            } catch (IllegalAccessException e) {  
                                e.printStackTrace();  
                            } catch (InvocationTargetException e) {  
                                e.printStackTrace();  
                            }  
                        }  
                    });  
                }  
            }  
        }  
    }  


> 这个核心代码就是使用反射获取其中的变量和方法,获取到绑定的view的控件(变量反射)和点击事件(方法反射)这里不做详细的解释,有时间我会在后面写一个关于反射的文章

第四步:其实上面已经完成了处理,我们只需要调用一下就可以了,像下面那样:

    setContentView(R.layout.activity_main);  
    //必须放在setContentView后面  
    InjectUtils.inject(this); 


下面,我们就可以运行一下项目,看看是不是达到我们的效果了。
项目地址: [https://github.com/coder-xiaoshuai/AnnotationDemo.git](https://github.com/coder-xiaoshuai/AnnotationDemo.git)

猜你喜欢

转载自blog.csdn.net/bencheng06/article/details/79400983
今日推荐