基于反射制作Ioc库(下)

  • 介绍
    在上一节我们已经完成了对ViewById注解的实现,从中我们可以发现先去获取Class声明的所有属性,然后遍历出带有我们预定义的注解的属性,我们自己在Activity子类声明的属性和Android Sdk自带Activity的属性其数量可想而知,这也是基于反射Ioc效率比较低下的原因,只有知道效率低的原因才可以对其改进,我们会在以后的文章中持续对其改进。在这里我们继续完成对Click注解的实现
  • 核心方法编写

  • 获取Class的所有方法

Method[] declaredMethods = clazz.getDeclaredMethods();
  • 遍历方法列表,找出带有Click注解的方法
for (Method method : declaredMethods) {
            if (method.isAnnotationPresent(Click.class)) {
                Click annotationClick = method.getAnnotation(Click.class);
                if (annotationClick != null) {
                    int viewId = annotationClick.value();
                    method.setAccessible(true);
                    View viewTarget =findViewById(viewId);
                    viewTarget.setTag(R.id.base_ioc_method_id, method);
                    viewTarget.setOnClickListener(iocListener);
                }
            }
        }

由于我们仅仅是为了说明原理,其中viewTarget.setTag(R.id.base_ioc_method_id, method);方法是通过唯一的id传递我们的方法Method,Andbase中支持点击事件类型比较多,是通过动态代理的方式实现。下面是iocListener部分

private OnClickListener iocListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            Method method = (Method) v.getTag(R.id.base_ioc_method_id);
            Class<?>[] parameterTypes = method.getParameterTypes();
            try {
                if (parameterTypes == null || parameterTypes.length == 0) {
                    Object[] objs = {};
                    method.invoke(ActivityBase.this, objs);
                } else if (parameterTypes.length == 1  &&View.class.isAssignableFrom(parameterTypes[0])) {
                    method.invoke(ActivityBase.this, v);
                } else {
                    throw new IllegalArgumentException("activitybase ioc param error");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    };

在onClick方法具体实现中,首先判断我们在Activity中声明的方法

@Click(R.id.tv)
public void onTvClicked() {
    toast("ioc onClick");
}

在这里我们并不需要TextView实例,但是有时候我们需要TextView的实例从而更新它的UI表现

@Click(R.id.tv)
public void onTvClicked(TextView tv) {
    tv.setText("ioc onClick");
}

所以在onClick中我们首先判断该Method的参数列表信息,如果需要View是实例我们就调用
method.invoke(this, v) 否则就调用method.invoke(this, new Object);

- 小结
到这里我们就完成了ViewById和Click注解的实现,其他双击事件、ListView的条目点击事件等原理类似,大家可以以此类推
这是我第一次写博客,鉴于技术水平和经验的不足,不免有错误产生,希望大家指正错误和改进方法,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值