开发者 · 2012年 11月 7日

[Eclipse]使用Fragment: 站在巨人的肩膀上

Android的ADT是开发安卓应用的得力工具,在实际使用中,我想对这套工具进行一点点定制:在新建的Android Application Project中拷贝一些特定的文件进去。
实现原理很简单,只要对Google原生的ADT中新建向导稍加修改,在最终performFinish时将制定目录下的文件拷贝到新建的项目中即可。可选的有至少三种方法:
最直接的就是修改ADT的代码,并重新编译ADT,预计代码量不到十行,可是重新打包ADT对于很多人是不能接受的,因为是直接修改别人代码,维护也困难。放弃。

第二种可以新写个插件,实现自己的newWizards,代码照抄ADT的NewProjectWizard。这样可以不用改变ADT的代码,我只要提供一个Plugin就行。但是ADT的Wizard引用了很多别的插件中的方法和资源,最后必然会因为抄了一个类而不得不抄更多的类更多的插件,简直和自己再写一套ADT没两样了。放弃。

第三种就是综合以上两种的优点,既不用写什么代码,又不破坏ADT的完整。那就是使用Fragment。

Fragment是一种特殊的插件,它需要一个host插件。我通常认为Fragment是寄生插件,需要一个寄主(host project)。在运行时(runtime),fragment工程会被合并(merge)到host工程中,并被当做一个project。因为这种寄生关系,fragment可以访问host插件的所有类和资源。从而fragment常用来测试plug-in的内部api。

结合前面提到的场景,我创建了一个基于com.android.ide.eclipse.adt的fragment:com.android.ide.eclipse.adt.ex。双击fragment.xml打开ManifestEditor,看起来和插件差不多,只不过有个Host Plug-in字段。

打开Extensions标签页,添加一个扩展:org.eclipse.ui.newWizards,新建一个wizard叫:Android Project Ex。id/name都跟新建wizard一样。icons/category/perspective照抄ADT的newWizard即可。
class:com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardEx(即新建的wizard的和ADT对应的在一个package路径下,但是名称不同,这样可以保证能访问到ADT对应的缺省类)。

万事俱备,只剩拷贝。

将com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizard的内容一股脑拷贝到com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardEx中。接下来就可以对performFinish为所欲为了,而且可以随便使用ADT中原来的Wizard能访问的一切资源,就像在自己家一样。而原生的ADT对这些方法一点也没辙。

打包发布这个fragment,会发现多了一个Android Application Project Ex的new wizard,这就是刚才新建的那个看起来一样,却夹带了私货的wizard。

使用这种方法,实现该功能,共耗时不到半个小时,clean and tidy。
类似的需要基于某个插件实现的功能,同样可以使用这样的方法,像站着巨人的肩膀上。