美文网首页
使用注解实现一个Android的IoC框架

使用注解实现一个Android的IoC框架

作者: 放羊娃华振 | 来源:发表于2019-12-02 14:42 被阅读0次

一、 概述

IoC,就是控制反转(Inversion of Control),缩写为 IoC。
简单来说,就是不需要手动 new 对象,只需要在配置文件或者注解指定一下类名,让框架去解析配置文件或者注解,然后利用反射实例化我们配置的类。

本文目的是利用注解实现setContentView、findViewById、setOnClickListener的代码由框架自动生成。

1.工程结构
image.png
2.体验代码
/**
 * @description 测试的Activity
 * @author: dzh
 * @CreateDate: ${DATE} ${TIME}
 */
@ContentView(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {

    @ViewInject(R.id.tvTest)
    TextView tvTest;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        Views.inject(this);
    }


    @OnClick(R.id.tvTest)
    public void showText(View v) {
        String text = tvTest.getText().toString();
        Toast.makeText(this, "获取到tvTest上的文本是:" + text, Toast.LENGTH_SHORT).show();
    }
}

二、具体实现步骤

1.创建绑定布局的注解
/**
 * @Description: 绑定布局
 * @Author: dzh
 * @CreateDate: 2019-12-02 13:59
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ContentView {

    int NONE = -1;

    int value() default NONE;
}
2.创建控件注入的注解
/**
 * @Description: 控件注入
 * @Author: dzh
 * @CreateDate: 2019-12-02 14:00
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {

    int NONE = -1;

    int value() default NONE;
}
3.创建绑定点击事件的注解
/**
 * @Description: 点击事件
 * @Author: dzh
 * @CreateDate: 2019-12-02 14:00
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OnClick {

    int NONE = -1;

    int value();
}
4.实现注解的解析类
/**
 * @Description: 注解解析类
 * @Author: dzh
 * @CreateDate: 2019-12-02 14:03
 */
public class Views {

    public static void inject(final Activity activity) {
        injectContentView(activity);
        injectViews(activity);
        injectOnClickListener(activity);
    }

    /**
     * 解析视图
     *
     * @param activity activity
     */
    private static void injectContentView(Activity activity) {
        Class<? extends Activity> activityClass = activity.getClass();
        ContentView contentViewAnnotation = activityClass.getAnnotation(ContentView.class);
        if (contentViewAnnotation == null) {
            return;
        }
        int layoutResId = contentViewAnnotation.value();
        if (layoutResId == ContentView.NONE) {
            return;
        }
        activity.setContentView(layoutResId);
    }

    /**
     * 解析控件
     *
     * @param activity activity
     */
    private static void injectViews(Activity activity) {
        Class<? extends Activity> activityClass = activity.getClass();
        Field[] fields = activityClass.getDeclaredFields();
        for (Field field : fields) {
            ViewInject viewInjectAnnotation = field.getAnnotation(ViewInject.class);
            if (viewInjectAnnotation == null) {
                continue;
            }
            int viewResId = viewInjectAnnotation.value();
            if (viewResId != ViewInject.NONE) {
                try {
                    View view = activity.findViewById(viewResId);
                    field.setAccessible(true);
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 解析点击事件
     *
     * @param activity activity
     */
    private static void injectOnClickListener(final Activity activity) {
        Class<? extends Activity> activityClass = activity.getClass();
        Method[] methods = activityClass.getDeclaredMethods();
        for (final Method method : methods) {
            OnClick onClickAnnotation = method.getAnnotation(OnClick.class);
            if (onClickAnnotation == null) {
                continue;
            }
            int viewResId = onClickAnnotation.value();
            if (viewResId == OnClick.NONE) {
                continue;
            }
            try {
                final View view = activity.findViewById(viewResId);
                if (view != null) {
                    view.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            try {
                                method.invoke(activity, view);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

三、总结

源码:https://github.com/stormdzh/AndroidIOC
通过反射实现,是运行时注解对性能有一定的影响!可以考虑是用apt实现。

参考来源

相关文章

网友评论

      本文标题:使用注解实现一个Android的IoC框架

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