美文网首页我爱编程Android开发经验谈Android技术知识
Android IOC架构,依赖注入(contentView,v

Android IOC架构,依赖注入(contentView,v

作者: MrLgc | 来源:发表于2018-04-12 19:02 被阅读0次

首先我们说说java元注解

@Target(注解的作用目标) @Retention(注解的保留位置)

@Ducument(说明该注解将包含在javadoc中) @Inherited(说明子类可以继承父类中的该注解)

1, @Target(ElmentType.Type) //同下

  ElementTypeTYPE      类、接口(包括注释类型)或枚举声明

  ElementTypeFIELD     字段声明(包括枚举常量)

  ElementTypeMETHOD    方法声明

  ElementTypePARAMETER     参数声明

  ElementTypeCONSTRUCTOR    构造方法声明

  ElementTypeLOCAL_VARIABLE     局部变量声明

  ElementTypeANNOTATION_TYPE     注释类型声明

  ElementTypePACKAGE    包声明

2,@Retention

@Retention(RetentionPolicy.SOURCE)//注解仅存在于源码中,在class字节码文件中不包含

@Retention(RetentionPolicy.CLASS)//注解class会字节码中,运行时无法获取,(默认策略)

@Retention(RetentionPolicy.RUNTIME)//注解会在class字节码中存在,运行时可以通过反射获取

框架实现

得进入正题了,Android IOC框架,其实主要就是帮大家注入所有的控件,布局文件什么的。如果你用过xUtils,afinal类的框架,你肯定不陌生~

MainActivity

@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {

    @ViewInject(R.id.tv_text)
    private TextView mTextView;

    @OnClick({R.id.btn})
    public void onClick(View view) {
        Toast.makeText(this, "按下", Toast.LENGTH_SHORT).show();
    }

    @OnLongClick({R.id.btn_long})
    public boolean onLongClick(View view) {
        Toast.makeText(this, "长按", Toast.LENGTH_SHORT).show();
        return true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ViewInjectUtils.inject(this);
        mTextView.setText("inject");
    }
}

ContentView

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

ViewInject

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

click事件

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@EventBase(listenerSetter = "setOnClickListener",
        listenerType = View.OnClickListener.class,
        callBackMethod = "onClick")
public @interface OnClick
{
    /**
     * 进行设置点击事件
     * @return
     */
    int[] value();
}

longclick事件

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@EventBase(listenerSetter = "setOnLongClickListener",
        listenerType = View.OnLongClickListener.class,callBackMethod = "onLongClick")
public @interface OnLongClick {
    int[] value() default -1;
}

ContentView注入

 /**
     * 注入ContentV
     *
     * @param activity
     */
    private static void injectContentView(AppCompatActivity activity) {
        Class<? extends AppCompatActivity> mClass = activity.getClass();
        ContentView contentView = mClass.getAnnotation(ContentView.class);
        if (contentView != null) {
            int layoutId = contentView.value();
            try {
                Method method = mClass.getMethod(METHOD_SET_CONTENTVIEW, int.class); //int.class 是一个引用
                method.setAccessible(true);
                method.invoke(activity, layoutId);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

View注入

/**
     * @param activity
     */
    private static void injectViews(AppCompatActivity activity) {
        Class<? extends AppCompatActivity> mClass = activity.getClass();
        //拿到所有变量
        Field[] mField = mClass.getDeclaredFields();
        for (Field field : mField) {
            ViewInject viewInject = field.getAnnotation(ViewInject.class);
            if (viewInject != null) {
                int id = viewInject.value();
                if (id != -1) {
                    try {
                        Method method = mClass.getMethod(METHOD_FIND_VIEW_BY_ID, int.class);
                        field.setAccessible(true);
                        Object view = method.invoke(activity, id);
                        field.set(activity, view);

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

Event事件注入

@Target(ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventBase {

    /**
     * 设置监听的方法
     * @return
     */
    String listenerSetter();

    /**
     * 事件类型
     * @return
     */
    Class<?> listenerType();

    /**
     * 回调方法
     * 事件被触发后,执行回调方法名称
     * @return
     */
    String callBackMethod();
}

  /**
     * 注入点击和长按事件
     * @param context
     */
    private static void injectEvents(AppCompatActivity context) {
        Class<?> clazz = context.getClass();
        Method[] methods = clazz.getDeclaredMethods();

        for (Method method : methods) {
            //获取方法上所有的注解
            Annotation[] annnotions = method.getAnnotations();
            for (Annotation annotation : annnotions) {

                //获取注解annotionType onClick OnLongClick
                Class<?> annotionType = annotation.annotationType();

                //获取注解的注解 onClick注解上面的EventBase
                EventBase eventBase = annotionType.getAnnotation(EventBase.class);
                if (eventBase == null) {
                    continue;
                }
                String listenerSetter = eventBase.listenerSetter();
                
                Class<?> listenerType = eventBase.listenerType();
                
                String callMethod = eventBase.callBackMethod();

                //方法名 与方法Method的对应关系
                Map<String, Method> methodMap = new HashMap<>();
                methodMap.put(callMethod, method);//eg:key:onClick(自己定义的)======value:MainActivity.onClick(Activity中的)

                try {
                    Method valueMethod = annotionType.getDeclaredMethod("value");
                    int[] viewIds = (int[]) valueMethod.invoke(annotation);

                    for (int viewId : viewIds) {
                        //通过反射拿到View
                        Method findViewById = clazz.getMethod("findViewById", int.class);
                        View view = (View) findViewById.invoke(context, viewId);
                        if (view == null) {
                            continue;
                        }

                        Method setOnClickListener = view.getClass().getMethod(listenerSetter, listenerType);

                        ListenerInvocationHandler handler = new ListenerInvocationHandler(context, methodMap);

                        //proxy 已经实现了listenerType接口
                        Object proxy = Proxy.newProxyInstance(
                                listenerType.getClassLoader(),
                                new Class[]{listenerType}, handler);
                        //接口里的方法有proxy来处理
                        setOnClickListener.invoke(view, proxy);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

    }

ListenerInvocationHandler

public class ListenerInvocationHandler implements InvocationHandler {
    //activity   真实对象
    private Context context;
    private Map<String, Method> methodMap;

    public ListenerInvocationHandler(Context context, Map<String, Method> methodMap) {
        this.context = context;
        this.methodMap = methodMap;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        //决定是否需要进行代理
        Method metf = methodMap.get(name);

        if (metf != null) {
            return metf.invoke(context, args);
        } else {
            return method.invoke(proxy, args);
        }
    }
}

相关文章

  • Android IOC架构,依赖注入(contentView,v

    首先我们说说java元注解 1, @Target(ElmentType.Type) //同下 2,@Reten...

  • Dagger2常用注解诠释

    依赖注入 控制反转(IoC)与依赖注入(DI)浅谈依赖注入理解依赖注入(IOC)和学习Unity Gradle配置...

  • 控制反转

    什么是控制反转(IOC),什么是依赖注入(DI)?问题:什么是控制反转(IOC),什么是依赖注入(DI)?IOC:...

  • 关于依赖注入(typescript)

    一、概念:依赖注入(DI)、控制反转(IOC)、IOC容器 依赖注入(DI)和控制反转(IOC)基本是一个意思,因...

  • 6.Spring IoC练习

    1. 依赖注入和控制反转 依赖注入和控制反转IoC是什么Ioc—InversionofControl,即“控制反转...

  • Spring学习之依赖注入

    Spring学习之依赖注入 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(...

  • Spring IOC容器

    由于Spring是采用依赖注入(DI)的方式来实现IOC,所以本文将IOC和依赖注入(DI)等同看待,主要讨论依赖...

  • Spring-Bean实例是如何依赖注入?

    那什么是依赖注入呢? 所谓依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中。再完成IOC容...

  • 一、Spring核心机制:依赖注入

    设值注入:IOC容器使用变量的setter方法来注入被依赖的对象。 构造注入:IOC容器使用构造器来注入被依赖的对...

  • 2018-09-27 Spring

    Spring IOC 容器 Spring IOC的理解 依赖注入(dependence injection):通过...

网友评论

    本文标题:Android IOC架构,依赖注入(contentView,v

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