1. 搭建Eclipse开发环境
1.1. 安装工具
-
Eclipse IDE for Java Developers或其超集(下载Kepler或之前的版本,因为AJDT目前只支持到Kepler版本)。
-
安装AspectJ Development Tools(AJDT) plugin(由于项目的部分代码用AspcectJ编写)。
-
安装Gradle Integration for Eclipse,并更改Gradle设置如下图。
1.2. 导入项目
下载项目,可以通过Eclipse Git客户端,或其它的Git客户端如TortoiseGit,git命令行等。这是项目地址。
下载完毕后按照以下步骤将项目导入Eclipse。
-
在command line下转到项目根路径。运行命令 'gradlew framework:cleanEclipse framework:eclipse'。
-
按Eclipse的Import 'Existing Projects into Workspace',将项目下的framework子项目导入。
-
以同样的方式你可以导入codegen子项目,如果对源代码生成有兴趣的话。
2. RoboBinding架构与实现
RoboBinding是一个实现Martin Fowler的Presentation Model构架模式的Android框架。 目标为减少Android应用开发工作量;促进清晰的项目结构;使项目代码更易于测试。
2.1. 从RoboBinding实现概览上看
以下"."表示相对于org.robobinding的包路径。
以上为RoboBinding框架实现的概要。黄色背景的两张图(Client与PresentationModel)为应用代码,其它的三个为框架代码。图中只列举了来自一些包的核心类。 Client(Activity, Fragment或Menu)将Layout传递给ViewBinder(或MenuBinder), ViewBinder从Layout文件构建起View层次结构(利用Android的内部android.view.LayoutInflater功能)以及RoboBinding绑定信息。 一个根View可能包含若干个子View,子View可能包含下级View,形成一个树状的结构。每一个View中可能包含若干个视图绑定属性。 RoboBinding中定义了三类视图绑定属性,分别是.viewattribute.property.[XX]PropertyViewAttribute, .viewattribute.event.EventViewAttribute, 以及.viewattribute.grouped.GroupedViewAttribute。
[XX]PropertyViewAttribute实现Layout中的显示数据与PresentationModel中的属性绑定; EventViewAttribute实现Layout中的事件与PresentationModel中的方法绑定; 而GroupedViewAttribute由若干个PropertyViewAttribute与EventViewAttribute组成,用于实现一个复合视图属性由多个子属性构成的情况。 PropertyViewAttribute通过.presentationmodel.PresentationModelAdapter 的.property.PropertyValueModel(如果是简单属性) 或.property.DataSetValueModel(如果是复杂的数据集合属性) 映射到PresentationModel的属性或数据集属性。 EventViewAttribute通过PresentationModelAdapter的.function.Function映射到PresentationModel的方法。
上图以实例解释了框架的实现概要。黄色背景的三张图摘自 RoboBinding-album-sample项目的源代码, 其它二个为应用运行时框架产生的对应的核心代码实例。 ViewAlbumsActivity通过框架(.binder.Binders类)将layout与presentationModel绑定在一起。
图中的第一个为简单视图属性的绑定例子。框架为{windowsTitle}
产生一个.widget.textview.TextAttribute实例,
而TextAttribute实例通过PresentationModelAdapter的PropertyValueModel
将{windowTitle}
与ViewAlbumsPresentationModel.windowTitle绑定在一起。
第二个为复合视图属性的绑定例子。ListView的source与itemLayout为复合视图属性,框架为{albums}
与@layout/album_row
产生一个.widget.adapterview.AdaptedDataSetAttributes复合视图属性实例,此复合视图属性包含两个子视图属性
.widget.adapterview.SourceAttribute与.widget.adapterview.StaticLayoutAttribute分别和{albums}
及其@layout/album_row
相对应。
而SourceAttribute实例通过PresentationModelAdapter的DataSetValueModel将{albums}
与ViewAlbumsPresentationModel.albums绑定在一起;
而StaticLayoutAttribute通过解析@layout/album_row
关联到外部文件album_row.xml。
第三个为事件视图属性的绑定例子。
框架为createAlbum
产生一个.widget.view.OnClickAttribute实例,而OnClickAttribute实例通过PresentationModelAdapter的Function
将createAlbum
与ViewAlbumsPresentationModel.createAlbum绑定在一起。
2.2. 从RoboBinding实现细节上看
2.2.1. 视图inflation与绑定实现
视图inflation与绑定实现类来自org.robobinding与org.robobinding.binder两个包。以下"."表示相对于org.robobinding的包路径。
如上图所示,应用开发者通过两个可能的入口点使用框架(以两种不同的颜色区分), .binder.Binders工具类或者.binder.BinderFactoryBuilder(可定制)。 不管是选择哪方式,其真正功能的入口类都是BinderFactory。 通过BinderFactory,创建一个ViewBinder实例。 使用ViewBinder完成layout的inflation以及绑定。 '接下来我们来说inflation的流程'。
上图展示了框架对一个layout进行inflation的整个流程及其主要的参与类。 接上述说到ViewBinder类,ViewBinder将layout inflation工作交给.binder.BindingViewInflater; 而layout inflation工作又被转交给org.robobinding.NonBindingViewInflater。NonBindingViewInflater只做layout inflation工作,不做解析视图绑定属性的工作, 它从layout文件创建视图集。当一个视图被创建时回调BindingViewInflater。 BindingViewInflater通过.binder.BindingAttributeParser解析出该视图的待绑定视图属性集org.robobinding.PendingAttributesForView。 就这样重复以上的过程,直到解析出layout中所有视图的待绑定视图属性集PendingAttributesForView为止。
然后待绑定视图属性集PendingAttributesForView被放入.binder.BindingAttributeResolver进行解析构建视图的绑定属性集。 BindingAttributeResolver通过.binder.ByBindingAttributeMappingResolverFinder从上至下为视图寻找匹配的绑定属性解析器集.binder.ByBindingAttributeMappingResolver (例如android.widget.EditText继承于android.widget.TextView,而TextView继承于android.view.View。一个EditText实例视图将匹配得到三个绑定属性解析器:EditText绑定属性解析器,TextView绑定属性解析器以及View绑定属性解析器。)。 BindingAttributeResolver通过调用所有匹配到的绑定属性解析器ByBindingAttributeMappingResolver得到最后的视图绑定属性集.binder.ResolvedBindingAttributesForView返回给BindingViewInflater。
BindingViewInflater接着添加所有预定义的待绑定视图属性集org.robobinding.PredefinedPendingAttributesForView,如果有的话。然后调用BindingAttributeResolver解析转化构建视图的绑定属性集, 过程与之前解析待绑定视图属性集PendingAttributesForView一致,最后也得到视图绑定属性集ResolvedBindingAttributesForView。
BindingViewInflater将包含所有视图绑定属性集ResolvedBindingAttributesForView的.binder.InflatedView返回给ViewBinder。整个layout的inflation工作结束。接着是下一步的绑定。
上图展示了整个绑定的过程以及主要的参与类。ViewBinder将绑定工作转给ViewBindingLifecycle。ViewBindingLifecycle运行并控制绑定生命周期。 通过调用上一步返回的InflatedView来绑定所有的视图绑定属性集ResolvedBindingAttributesForView。 而视图绑定属性集ResolvedBindingAttributesForView内部又调用各个视图绑定属性完成绑定。 绑定完成之后,ViewBindingLifecycle校验所有绑定是否都成功,不成功就终止并报告错误。如果成功,就接着预初始化视图值(如果需要的话)。 预初始化视图值即将PresentationModel的初值设置到视图上。
2.2.2. 视图绑定属性实现
视图绑定属性由org.robobinding.viewattribute及其子包提供实现。以下"."表示相对于org.robobinding.viewattribute的包路径。
视图属性主要包含三类:简单视图属性.property.PropertyViewAttribute, 事件视图属性.event.EventViewAttribute, 以及复合视图属性.grouped.GroupedViewAttribute。
PropertyViewAttribute为简单视图属性绑定提供实现,
分为两种,即单值简单视图属性.property.PropertyViewAttribute与多值简单视图属性.property.MultiTypePropertyViewAttribute。
单值简单视图属性PropertyViewAttribute(如图[1.1]标注的{enabledSwitch}
,{selectedSwitch}
)
即只有一种可能类型的值如EnabledAttribute(org.robobinding.widget.view.EnabledAttribute),只有Boolean类型的值。
多值简单视图属性MultiTypePropertyViewAttribute(如图[1.2]标注的{visibilitySwitch}
)
即有多种可能类型的值如VisibilityAttribute(org.robobinding.widget.view.VisibilityAttribute)控制是否可视,可能有Boolean或Integer类型的值。
EventViewAttribute(如图[2]标注的onClick
,onLongClick
)为事件视图属性绑定提供实现,
如org.robobinding.widget.view.OnClickAttribute/OnLongClickAttribute等。
GroupedViewAttribute(如图[3.1,3.2]标注的{source}
,@layout/item_row
,{[text1.text:{name}]}
;@layout/footer_layout
,{footer}
,{footerVisibility}
)
为复合视图属性绑定提供实现,如AdaptedDataSetAttributes(org.robobinding.widget.adapterview.AdaptedDataSetAttributes)由子属性source,itemLayout以及可选的itemMapping构成;
org.robobinding.widget.listview.FooterAttributes由子属性footerLayout以及可选的footerPresentationModel与footerVisibility构成。
org.robobinding.viewattribute包 包含了主要的概念抽象类,而org.robobinding.widget子包对应android.widget包下的各种widget的视图属性绑定实现。 如org.robobinding.widget.textview包对应android.widget.TextView;org.robobinding.widget.seekbar包对应android.widget.SeekBar。
各种视图属性都有对应的Binder类组合完成绑定工作,如EventViewAttribute对应着EventViewAttributeBinder。
以下"."表示相对于org.robobinding.viewattribute的包路径。
上图展示了.group.GroupedViewAttribute复合视图属性与子属性的关系。GroupedViewAttribute包含了各种类型的子属性,目前主要包含这几类,即.grouped.ChildViewAttribute, .grouped.DependentChildViewAttribute,property.PropertyViewAttribute以及property.MultiTypePropertyValueAttribute。
ChildViewAttribute为普通的子视图属性,其下又包含了.grouped.ChildViewAttributeWithAttribute;ChildViewAttributeWithAttribute为带属性值的子视图属性,在该子属性被创建时, 框架将赋予所需的属性值,例如:org.robobinding.widget.adapterview.SourceAttribute/SubViewLayoutAttribute。
DependentChildViewAttribute为依赖型子视图属性,该类型的子视图属性不能被简单的被创建,它们依赖于前面子属性的信息, 而由一个.grouped.ChildViewAttributeFactory工厂创建;例如org.robobinding.widget.adapterview.SubViewAttributes.SubViewAttributeFactory, 创建SubViewAttribute依赖于subViewLayoutAttribute.getLayoutId()。
PropertyViewAttribute与MultiTypePropertyViewAttribute为单值与多值简单视图属性,前面已经提到过,可以重用系统中已有的简单视图属性作为复合视图属性的子属性。
2.2.3. Presentation Model概念实现
以下"."表示相对于org.robobinding的包路径。
Presentation Model相关概念实现类主要来自org.robobinding.presentationmodel,org.robobinding.property,org.robobinding.itempresentationmodel以及org.robobinding.function这四个包。 这些类主要用于包装应用程序的PresentationModel以便于绑定模块使用。.presentationmodel.PresentationModelAdapter为这几个包的入口类。 框架为应用程序的每一个PresentationModel生成一个对应的PresentationModelAdapter实例。 框架通过@org.robobinding.presentationmodel.PresentationModel来识别应用程序PresentationModel。
PresentationModelAdapter主要包装PresentationModel的三类信息,
即将SimpleProperty,DataSetProperty和Method包装为.property.PropertyValueModel,.property.DataSetValueModel
和.function.Function。上图右边的例子中:windowTitle
为SimpleProperty,albums
为DataSetProperty,createAlbum()
为Method。
DataSetProperty是一个数据集属性,其中每一个数据项又会生成一个.itempresentationmodel.ItemPresentationModel实例,
上图中即为AlbumItemPresentationModel,其与对应的@layout/album_row
配合显示相应的行。
2.2.4. 视图事件监听器聚集
视图事件监听器聚集(即org.robobinding.viewattribute.ViewListeners或其子类),这是由于android框架的事件设计而提供的一个workaround。 因为android框架中很多事件只能注册一个事件监听器如android.view.View.setOnFocusChangeListener,但应用中有时可能需要注册多个, 为了使之前注册过的旧的事件监听器不被新的意外覆盖而提供了事件监听器聚集ViewListeners。
3. 贡献
-
我们注重代码质量。所有的代码,特别是公共方法都必须有单元测试。如果没有办法提供单元测试必须明确说明理由。
-
代码依照RoboBinding的格式统一要求,这样方便大家一起协作贡献。我们所用的格式其实是Sun的标准格式。