美文网首页Android进阶之路Android开发经验谈Android技术知识
利用反射和注解手撸一个Android依赖注入框架

利用反射和注解手撸一个Android依赖注入框架

作者: 肖邦kaka | 来源:发表于2020-03-30 23:53 被阅读0次

    前言

    本文是系列文章的第三篇,利用前两篇的反射注解来手撸一个Android依赖注入框架,还没有学习过前两篇文章内容的小伙伴,抓紧学习一下吧。

    创建注解

    这里我们以Butterknife的ViewBind和OnClick为例,创建这么两个注解,直接上代码

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ViewBind {
        int value();
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface OnClick {
        int value();
    }
    

    这里没有什么特别要说,这两个注解需要用反射来解析,所以生命周期都要保留到RUNTIME(运行时),一个需要作用到成员变量上,一个作用到方法上。

    创建注解解析器

    光有了注解还不行,必须要有与之对应的注解解析器来解析注解,这里我们利用反射,直接上代码

    public class ViewInjust {
    
        public static void bind(Activity activity){
            bindView(activity);
            bindClick(activity);
        }
    
        private static void bindView(Activity activity) {
            Class<? extends Activity> aClass = activity.getClass();//拿到class类对象
            Field[] declaredFields = aClass.getDeclaredFields();//拿到所有的成员变量
            for (Field field:declaredFields) {//遍历成员变量
                if (field.isAnnotationPresent(ViewBind.class)) {//判断该变量是否被注解
                    ViewBind annotation = field.getAnnotation(ViewBind.class);//获得ViewBind
                    int viewId = annotation.value();//拿到viewId
                    View view = activity.findViewById(viewId);//拿到view
                    try {
                        field.setAccessible(true);//取消安全检查机制
                        field.set(activity,view);//把view赋值给当前成员变量
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private static void bindClick(final Activity activity) {
            Class<? extends Activity> aClass = activity.getClass();//拿到class类对象
            Method[] declaredMethods = aClass.getDeclaredMethods();//拿到所有的方法
            for (final Method method:declaredMethods) {//遍历所有的方法
                if (method.isAnnotationPresent(OnClick.class)) {
                    OnClick annotation = method.getAnnotation(OnClick.class);//获得Onclick注解
                    int viewId = annotation.value();
                    View view = activity.findViewById(viewId);
                    view.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            try {
                                method.setAccessible(true);//取消安全检查机制
                                method.invoke(activity,null);//调用对应的方法
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            }
        }
    }
    

    代码上面都有充分的注释,主要运用就是我们在第一篇中学到的反射的知识。

    测试一下

    public class MainActivity extends AppCompatActivity {
    
        @ViewBind(R.id.textView)
        TextView textView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ViewInjust.bind(this);
            textView.setText("测试绑定");
        }
    
        @OnClick(R.id.button)
        private void clickBtn(){
            Toast.makeText(getApplicationContext(),"点击了按钮",Toast.LENGTH_SHORT).show();
        }
    }
    

    测试结果


    测试结果.jpg

    总结

    这篇文章是我写过的文章中最简单、内容最少的一篇,我原本不想写来着,但是作为一个系列文章,还是有必要把前面两篇文章的内容串起来一下并巩固一番。但是你以为Butterknife就是像本文的实现那么简单吗?当然不是,之前也有提到过反射的性能会比较差,这样大规模且频繁地使用就会更差,所以Butterknife用了一个更加高深的方式。我将在下一篇文章中为大家详解Butterknife并亲自手撸一个出来,敬请期待吧!

    相关文章

      网友评论

        本文标题:利用反射和注解手撸一个Android依赖注入框架

        本文链接:https://www.haomeiwen.com/subject/imabuhtx.html