我在想
寫(xiě)RecyclerView的適配器時(shí)我就在想了,每一個(gè)適配器的創(chuàng)建步驟幾乎完全一樣,不同的僅僅只是ViewHolder,或者說(shuō)view的數(shù)量和Id。
既然如此,就沒(méi)有一個(gè)辦法去除這些重復(fù)的工作嗎……沒(méi)有,我還是得重復(fù)寫(xiě)Holder。
于是我開(kāi)始思考,最終得到了兩個(gè)方法:
1.寫(xiě)一個(gè)自動(dòng)生成Adapter和Holder的插件。
2.封裝一個(gè)Adapter,屏蔽掉重復(fù)的,約定俗成的工作,就像Springboot做的那樣。
我選擇了后者。我希望在不改變?cè)瓉?lái)的編碼方式的前提下,根據(jù)布局文件自動(dòng)生成ViewHolder。問(wèn)題的核心變成了,如何動(dòng)態(tài)生成一個(gè)類……解決方案很簡(jiǎn)單,因?yàn)閖ava的編譯器被那些人用java重寫(xiě)了,所以我輕易得到了一個(gè)把Java代碼的字符串轉(zhuǎn)換成對(duì)象的方案。在這個(gè)基礎(chǔ)上,獲取布局文件里所有設(shè)置了id的子View,并根據(jù)View的類型拼接初始化的代碼,最后用拼接好的ViewHolder的代碼,直接生成ViewHolder對(duì)象。
新的問(wèn)題來(lái)了,動(dòng)態(tài)生成的ViewHolder類在編譯期是不存在的……我沒(méi)有辦法訪問(wèn)一個(gè)不存在的類的對(duì)象,即使運(yùn)行時(shí)這個(gè)類確實(shí)存在,但是在我寫(xiě)代碼的過(guò)程中,它就是不存在的……
很矛盾。明明就知道在運(yùn)行時(shí)一定存在那個(gè)類,編譯器還是認(rèn)為我的代碼有問(wèn)題。
解決方案是用反射訪問(wèn)。但是這樣違背了初衷,我想要的是不改變?cè)瓉?lái)寫(xiě)代碼的方式,原來(lái)直接用holder.view訪問(wèn),現(xiàn)在也必須用一樣的方式。
無(wú)解。核心問(wèn)題是ViewHolder是動(dòng)態(tài)生成的,編譯期并不存在這個(gè)類……當(dāng)然,可以把訪問(wèn)ViewHolder的類,也就是整個(gè)Adapter都動(dòng)態(tài)生成來(lái)解決這個(gè)問(wèn)題,但是這樣就要訪問(wèn)一個(gè)不存在的Adapter……
可以整一個(gè)Adapter的父類來(lái)解決上面的問(wèn)題,把訪問(wèn)ViewHolder的方法定義成抽象方法交給子類去實(shí)現(xiàn),這樣即使把動(dòng)態(tài)生成的Adapter強(qiáng)轉(zhuǎn)成父類的類型,那一部分的實(shí)現(xiàn)依舊是子類。
就很詭異,Java允許程序員定義一個(gè)并不存在的方法:我可以告訴編譯器,某個(gè)類存在某個(gè)方法,但是我不知道這個(gè)方法的實(shí)現(xiàn)。然而沒(méi)辦法定義一個(gè)不存在的字段,不能說(shuō)某個(gè)類存在某個(gè)字段,但是我不知道字段的作用。
一切的字段,在定義的那一刻就已經(jīng)被確定了用途,然而抽象方法卻可以有無(wú)數(shù)種用途。
其實(shí)還是有解的,java最終會(huì)編譯成smail,只要讓smail代碼訪問(wèn)那個(gè)不存在的類就好。
問(wèn)題的核心變成了,怎么強(qiáng)制讓編譯器生成smail……但是這樣做沒(méi)有意義,成本太高。
光想才是真的沒(méi)有意義,怎么動(dòng)手實(shí)現(xiàn)才是問(wèn)題的核心。