我在想
写RecyclerView的适配器时我就在想了,每一个适配器的创建步骤几乎完全一样,不同的仅仅只是ViewHolder,或者说view的数量和Id。
既然如此,就没有一个办法去除这些重复的工作吗……没有,我还是得重复写Holder。
于是我开始思考,最终得到了两个方法:
1.写一个自动生成Adapter和Holder的插件。
2.封装一个Adapter,屏蔽掉重复的,约定俗成的工作,就像Springboot做的那样。
我选择了后者。我希望在不改变原来的编码方式的前提下,根据布局文件自动生成ViewHolder。问题的核心变成了,如何动态生成一个类……解决方案很简单,因为java的编译器被那些人用java重写了,所以我轻易得到了一个把Java代码的字符串转换成对象的方案。在这个基础上,获取布局文件里所有设置了id的子View,并根据View的类型拼接初始化的代码,最后用拼接好的ViewHolder的代码,直接生成ViewHolder对象。
新的问题来了,动态生成的ViewHolder类在编译期是不存在的……我没有办法访问一个不存在的类的对象,即使运行时这个类确实存在,但是在我写代码的过程中,它就是不存在的……
很矛盾。明明就知道在运行时一定存在那个类,编译器还是认为我的代码有问题。
解决方案是用反射访问。但是这样违背了初衷,我想要的是不改变原来写代码的方式,原来直接用holder.view访问,现在也必须用一样的方式。
无解。核心问题是ViewHolder是动态生成的,编译期并不存在这个类……当然,可以把访问ViewHolder的类,也就是整个Adapter都动态生成来解决这个问题,但是这样就要访问一个不存在的Adapter……
可以整一个Adapter的父类来解决上面的问题,把访问ViewHolder的方法定义成抽象方法交给子类去实现,这样即使把动态生成的Adapter强转成父类的类型,那一部分的实现依旧是子类。
就很诡异,Java允许程序员定义一个并不存在的方法:我可以告诉编译器,某个类存在某个方法,但是我不知道这个方法的实现。然而没办法定义一个不存在的字段,不能说某个类存在某个字段,但是我不知道字段的作用。
一切的字段,在定义的那一刻就已经被确定了用途,然而抽象方法却可以有无数种用途。
其实还是有解的,java最终会编译成smail,只要让smail代码访问那个不存在的类就好。
问题的核心变成了,怎么强制让编译器生成smail……但是这样做没有意义,成本太高。
光想才是真的没有意义,怎么动手实现才是问题的核心。