Android进阶之路Android开发经验谈Android技术知识

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

2020-03-30  本文已影响0人  肖邦kaka

前言

本文是系列文章的第三篇,利用前两篇的反射注解来手撸一个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并亲自手撸一个出来,敬请期待吧!

上一篇下一篇

猜你喜欢

热点阅读