[造轮子]一个脑洞大开的DataBinding Demo

之前看了一下RoboBinding的源码,还YY了一下不用Annotation的做法。自己蛋疼的做了一个极简的demo,顿觉纸上得来终觉浅,绝知此事要躬行。

总起

抽象来说,DataBinding和ButterKnife、ORMLite都是通过生成代码来减少垃圾代码量,让整体代码更加整洁。Java实现这个主要在两个阶段实现:
- 运行时:Annotation+调用反射的代码(印象中ButterKnife是这样的);切面(限制比较多,AspectJ);Proxy(这个也有一些限制,用起来也是很nb)
- 编译时:AnnotationProcessor+编译时生成(通用,对开发流程入侵极少的方法);类描述文件+FreeMarker(参见GreenDAO,个人非常喜欢这个方法,因为简单、高效、多种功能简单共存)

思路

在DataBinding这个场景里,实现也有上面两种方法:运行时靠反射绑定一切,非常简单的实现原理,但是可能有性能问题;AnnotationProcessor生成代码,减少运行时的反射(RoboBinding方案)。
我脑洞比较大,不想用反射,也不喜欢AnnotationProcessor生成类的麻烦,就用了类描述文件+FreeMarker(GreenDAO的方式,所以demo也就叫GreenBinding):类描述文件直接用代码搞,方便快捷,生成供使用的ViewModel。

ViewModel

ViewModel是凝聚了整个Demo最精华的部分。对象在我看来,除掉性能差距就是一个加上了编译时和运行时类型校验的Map<String, Object>,而运行时类型校验发生在getter和setter的执行时;而成员方法则可视为一个带参数的Runnable(当然Java8的方法指针更精准,公司不让用就没搞过)。那么,一个对象,如果想不用反射还要极致的运行时灵活性,最简单的办法就是把对象抽象成两个Map:

    protected Map<String, Object> mFields = new HashMap<>();
    protected Map<String, ICommand> mCommands = new HashMap<>();

    public Object invoke(String name, Object... params) {
        ICommand command = mCommands.get(name);
        if (null == command) {
            return null;
        }
        return command.invoke(this, params);
    }

    public void set(String name, Object value) {
        Object v = mFields.get(name);
        if (check(v, value)) {
            return;
        }
        mFields.put(name, value);
        notifyChange(name, value);
    }

    public Object get(String name){
        return mFields.get(name);
    }

当然对外接口肯定要保持正常对象的样子。

Binding

Data有了,那就剩Binding了。大体上就是通过Factory,在inflate的时候获取到View和自定义的标签。根据标签绑定事件和数据。

  • Factory是拿不到View引用的,所以要改造一下,用自己的Factory2复制LayoutInflater.createViewFromTag的主流程:反射出LayoutInflater(这是个基类)中的mFactory、mFactory2、mPrivateFactory;按LayoutInflater源码里面的顺序(mFactory2-mFactory-mPrivateFactory)依次调用,试图获取到一个View;在我的手机上(一加2)是获取不到的,还要再调一下LayoutInflater的createView(还是源码的逻辑)才能获得最终创建出来的View
  • View有复杂的继承关系,View支持的事件和标签与View的类型有关。这时候,用View的class做Strategy模式是最合理的方案。每个View对应着一个Handler,处理对应View的标签,Handler之间的继承关系与View相同。我代码里用的是组合,不是继承,看起来不够优雅
  • 一定要想好内存泄漏问题,对于引用复杂的对象,要有dispose接口

代码见GreenBinding

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值