实现注入view,简单案例剖析butterknife原理

来源:互联网 发布:mac怎么卸载百度云盘 编辑:程序博客网 时间:2024/04/29 07:52

ButterKnife注入框架我相信大家都用过至少听过吧,它的出现简直是android开发人员的一大福利,彻底解放了无止境的findViewById,而是通过优雅的注解来实现view的赋值,如果你真没听过那我在这里只能贴上一张github的截图,自己好好反思吧~

butterKnife地址

这里写图片描述

1w5的star你还有什么不学的理由!!!

好的,今天我们不说butterfnife怎么用,而是仿照框架中的实现原理,用最简单的例子自己来实现view的注入!

1、编写自定义注解类

既然是注入的形式对view赋值,那么当然少不了注解,我们最常用的莫过于setContentView和findViewById,我们先来定义这两个注解(注释中顺便帮同学们补一些注解的知识):

setContentView

/** * @Target描述注解的使用范围 * 1.CONSTRUCTOR:用于描述构造器  2.FIELD:用于描述域  3.LOCAL_VARIABLE:用于描述局部变量  4.METHOD:用于描述方法  5.PACKAGE:用于描述包  6.PARAMETER:用于描述参数  7.TYPE:用于描述类、接口(包括注解类型) 或enum声明 */@Target(ElementType.TYPE)/** *  @Retention 该Annotation被保留的时间长短 *   1.SOURCE:在源文件中有效(即源文件保留)   2.CLASS:在class文件中有效(即class保留)   3.RUNTIME:在运行时有效(即运行时保留) */@Retention(RetentionPolicy.CLASS)public @interface SetContent {    int value() default -1;}

findViewById

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

注解定义好之后,我们的目标是在activity中这样使用对不对

@SetContent(R.layout.activity_main)public class MainActivity extends AppCompatActivity {    @BindView(R.id.tv_text)    private TextView textView;}

这是我们需要一个解析器。

2、编写注解解析器,为这些view赋值

/** * Created by admin on 2017/4/2. * 注入解析器 * 单例 */public class MyAnnotationInject {    private static MyAnnotationInject INSTANCE;    private List<Object> mInjectObjs = new ArrayList<Object>();    public static MyAnnotationInject init() {        if (INSTANCE == null) {            INSTANCE = new MyAnnotationInject();        }        return INSTANCE;    }    /**     * 注册需要注入的类对象     * @param injectObj     */    public void regist(@NonNull Object injectObj) {        if(mInjectObjs.contains(injectObj)){            return;        }        if (injectObj instanceof Activity) {            Activity activity = (Activity) injectObj;            //拿到注入的class对象            Class<Activity> clz = (Class<Activity>) activity.getClass();            try {                injectContentView(activity, clz);                injectView(activity, clz);            } catch (IllegalAccessException e) {                e.printStackTrace();            }        }        mInjectObjs.add(injectObj);    }    /**     * 注入view     */    private void injectView(Activity activity, Class<Activity> clz) throws IllegalAccessException {        //获得所有的属性,包括public、protected、private        Field[] fields = clz.getDeclaredFields();        for (Field field : fields) {            //遍历所有属性,找到标有Bindview注解的属性            if (field.isAnnotationPresent(BindView.class)) {                //拿到BindView注解的值                BindView annotation = field.getAnnotation(BindView.class);                int viewId = annotation.value();                //如果是私有属性,修改属性赋值之前必须加可修改权限                field.setAccessible(true);                //给属性重新赋值,参数1:要修改的属性的对象 , 参数2 : 新值                field.set(activity, activity.findViewById(viewId));            }        }    }    /**     * 注入activity布局     */    private void injectContentView(Activity activity, Class<Activity> clz) {        if (clz.isAnnotationPresent(SetContent.class)) {            //拿到SetContent注解的值            SetContent annotation = clz.getAnnotation(SetContent.class);            int resId = annotation.value();            if (resId != -1) {                activity.setContentView(resId);            }        }    }    /**     * 注销需要注入的类对象     * @param injectObj     */    public void unRegist(Object injectObj) {        if (mInjectObjs.contains(injectObj))            mInjectObjs.remove(injectObj);    }}

3、Activity中使用我们的注解来代替findViewById

@SetContent(R.layout.activity_main)public class MainActivity extends AppCompatActivity {    @BindView(R.id.tv_text)    private TextView textView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        MyAnnotationInject.init().regist(this);        textView.setText("通过注解注入view成功!");    }    @Override    protected void onDestroy() {        super.onDestroy();        MyAnnotationInject.init().unRegist(this);    }}

我们看一下效果:
这里写图片描述

当然我这只是butterknife中冰山一角,如果想要具体学习整个框架可以去学习butterknife的源码~
butterKnife地址,点我

0 0
原创粉丝点击