美文网首页
Android 中的 IOC 框架

Android 中的 IOC 框架

作者: 青涩记忆 | 来源:发表于2018-04-20 18:01 被阅读0次
IoC,控制反转(Inversion of Control,英文缩写为IoC)
要完成IoC框架,首先你需要了解注解与发射
开始代码片段

Activity setContentView注解

@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {
    int value();
}

字段注解

@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    int value();
}

事件三要素注解

@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BaseEvent {
    String setMethodName();
    Class<?> interfaceClass();
    String callMethodName();
}

OnClick注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnClickListener", interfaceClass = View.OnClickListener.class, callMethodName = "onClick")
public @interface OnClick {
    int[] value();
}

OnLongClick注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnLongClickListener", interfaceClass = View.OnLongClickListener.class, callMethodName = "onLongClick")
public @interface OnLongClick {
    int[] value();
}

OnItemClick注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@BaseEvent(setMethodName = "setOnItemClickListener", interfaceClass = AdapterView.OnItemClickListener.class, callMethodName = "onItemClick")
public @interface OnItemClick {
    int[] value();
}

动态代理

 * 动态代理
 */
public class EventInvocationHandler implements InvocationHandler {
    //代理的方法
    private Map<String,Method>map;
    //代理的真实对象
    private Object target;

    public EventInvocationHandler(Map<String, Method> map, Object target) {
        this.map = map;
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName=method.getName();
        if(map.get(methodName)!=null){
            return map.get(methodName).invoke(target,args);
        }
        return proxy;
    }
}

注解contentview实现

        //获取当前的类
        Class cls = context.getClass();
        //获取类上面的ContentView注解
        ContentView contentViewAnnotation = (ContentView) cls.getAnnotation(ContentView.class);
        if (contentViewAnnotation != null) {
            //获取注解上的值
            int value = contentViewAnnotation.value();
            try {
                //在类里面查找setContentView方法
                Method setContentViewMethod = cls.getMethod("setContentView", int.class);
                //setContentView调用
                setContentViewMethod.invoke(context, value);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

    }

注解字段的实现

        //获取当前的类
        Class cls = context.getClass();
        //查找对应的属性
        Field[] fields = cls.getFields();
        //遍历属性找到BindView注解
        for (Field field : fields) {
            BindView bindView = field.getAnnotation(BindView.class);
            if (bindView != null) {
                //获取注解的值
                int value = bindView.value();
                try {
                    //获取findVIewById方法
                    Method findViewByIdMethod = cls.getMethod("findViewById", int.class);
                    //调用findViewById方法拿到返回值
                    Object view = findViewByIdMethod.invoke(context, value);
                    field.setAccessible(true);
                    //设置属性值
                    field.set(context, view);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }

注解事件的实现

        //获取当前的类
        Class cls = context.getClass();
        //获取类中申明的可见方法
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            //获取方法上的所有注解
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                //获取注解的类型 此处为OnClick OnLongClick
                Class<?> annotationType = annotation.annotationType();
                //获取事件注解
                BaseEvent baseEvent = annotationType.getAnnotation(BaseEvent.class);
                if (baseEvent != null) {
                    //获取事件注解三要素
                    String setMethodName = baseEvent.setMethodName();
                    Class<?> interfaceClass = baseEvent.interfaceClass();
                    String callMethodName = baseEvent.callMethodName();
                    //为动态代理做准备
                    Map<String, Method> map = new HashMap<>();
                    map.put(callMethodName, method);

                    try {
                        //获取注解的方法 值OnClick  OnLongClick
                        Method valueMethod = annotationType.getDeclaredMethod("value");
                        int[] values = (int[]) valueMethod.invoke(annotation);
                        for (int value : values) {
                            //通过注解的值 找到对应的view
                            Method findViewById = cls.getMethod("findViewById", int.class);
                            Object view = findViewById.invoke(context, value);
                            //获取事件的方法
                            Method setEventMethod = view.getClass().getMethod(setMethodName, interfaceClass);
                            //动态代理 代理context里面的方法
                            EventInvocationHandler eventInvocationHandler = new EventInvocationHandler(map, context);
                            Object proxy = Proxy.newProxyInstance(view.getClass().getClassLoader(), new Class<?>[]{interfaceClass}, eventInvocationHandler);
                            //调用方法,通过动态代理最终执行context里面的方法
                            setEventMethod.invoke(view, proxy);
                        }
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

上面只是简单的实现,可能的内存泄露,大家可以考虑使用引用相关的知识!

最后附上demo地址

相关文章

  • 注解框架源码分析(XUtils、ButterKnife)

    1.前言 频繁的findViewById是一件挺烦人的事,IOC注解框架应运而生,Android中IOC框架就是注...

  • Afinal简介

    Afinal 是一个android的sqlite orm 和 ioc 框架。同时封装了android中的http框...

  • Android 中的 IOC 框架

    IoC,控制反转(Inversion of Control,英文缩写为IoC) 要完成IoC框架,首先你需要了解注...

  • Android Annotations

    Android主流IOC框架浅析 Android Annotations,ButterKnife,Dagger,R...

  • MVPArms到Dagger2

    Dagger2 介绍 一般的IOC框架都是通过反射来实现的,单Dagger2作为android端的IOC框架,为了...

  • Android中手撸IOC框架

    在刚接触安卓的第二天 , 自己最熟悉的代码 , 就是那句findViewById. 记得当时特别舒服的啪啪啪敲完一...

  • Spring AOP编程实战

    Spring框架的IOC功能之注解的方式 Spring框架的IOC之注解方式的快速入门 Spring框架中Bean...

  • awesome-android

    afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...

  • awesome-android

    afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...

  • 2018-08-20

    spring框架中IoC和aop 1. IoC(Inversion of Control) (1) 控制反转:这...

网友评论

      本文标题:Android 中的 IOC 框架

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