在前面的文章之中,我们介绍了向日葵甘特图的数据结构,在这篇文章,将主要介绍如何给甘特图提供数据。
向日葵甘特图采用数据适配器的机制来获取数据,这意味着你可以将你的任何格式和来源的数据提供给甘特图,实现的一个数据适配器的接口非常简单,现在我们以目前向日葵实现的任务甘特图为例,来介绍数据适配器的原理。
下面是SFData对象和数据适配器之间的工作流程图:
上面的蓝线代表SFData向数据适配器读取数据的过程,SFData在必要的时候想数据适配器请求数据,而数据适配器返回对应的数据,红线代表SFData在更改数据之后通知数据适配器的过程,这样数据适配器可以进行相应的更新以保持两者的数据一致,也可以将数据更改提交到服务器保存。
关于数据适配器的,有以下要点需要注意:
1.数据适配器只和SFData交互,甘特图之中的其他对象都是访问SFData对象,而不会直接访问数据适配器;
2.任何的任务、资源、链接、分配等对象不会被重复读取,SFData在读取一次之后后面不再向数据适配器请求而直接返回,这样保证逻辑的清晰,并保证数据读取的性能。
3.SFData对数据的访问都是单个的单元,也就是说,每次仅仅请求一个特定的任务或其他对象,因此数据适配器可以实现数据的分块加载,尤其是数据量比较大的时候,应该每次向服务器读取少量的数据,然后在下次收到SFData请求的时候再去请求。
4.没有必要支持数据适配器的所有功能,例如你不需要将数据的更改通过数据适配器保存到服务端,就可以完全不用支持用来接收更改通知的所有方法
我们现在来看看数据适配器一共有哪些接口:
接口类型 | 接口方法 | 返回值类型 | 接口描述 |
initialize() | 通知适配器开始初始化 | ||
获取配置 | getCalendar() | SFWorkingCalendar对象 | 返回当前数据使用的工作日历 |
请求数据 | readRootTask() | SFDataTask对象 | 返回文档根任务 |
请求数据 | readTaskFirstChild(task) | SFDataTask对象 | 返回指定任务的第一个子任务,如果不存在则返回null,只有在任务的Summary属性为true的时候才可能调用 |
请求数据 | readTaskNextSibling(task) | SFDataTask对象 | 返回指定任务的下一个兄弟任务,如果不存在则返回null |
请求数据 | readRootResource() | SFDataResource对象 | 返回文档根资源 |
请求数据 | readResourceFirstChild(resource) | SFDataResource对象 | 返回指定资源的第一个子资源,如果不存在则返回null,只有在资源的Summary属性为true的时候才可能调用 |
请求数据 | readResourceNextSibling(resource) | SFDataResource对象 | 返回指定资源的下一个兄弟资源,如果不存在则返回null |
请求数据 | readTaskFirstLink(task) | SFDataLink对象 | 返回指定任务的第一个链接 |
请求数据 | readTaskNextLink(task,link) | SFDataLink对象 | 返回指定任务的下一个链接 |
请求数据 | readTaskFirstAssignment(task) | SFDataAssignment对象 | 返回指定任务的第一个资源分配 |
请求数据 | readTaskNextAssignment(task,assignment) | SFDataAssignment对象 | 返回指定任务的下一个资源分配 |
请求数据 | readResourceFirstAssignment(task) | SFDataAssignment对象 | 返回指定资源的第一个分配任务 |
请求数据 | readResourceNextAssignment(resource,assignment) | SFDataAssignment对象 | 返回指定资源的下一个分配任务 |
通知更改 | updateTask(task,property,value) | 通知修改任务 | |
通知更改 | addTask(parent,pTask) | 通知添加任务 | |
通知更改 | deleteTask(task) | 通知删除任务 | |
通知更改 | moveTask(task,parentTask,previousSibling) | 通知移动任务 | |
通知更改 | updateResource(task,property,value) | 通知修改资源 | |
通知更改 | addResource(parent,pResource) | 通知添加资源 | |
通知更改 | deleteResource(resource) | 通知删除资源 | |
通知更改 | moveResource(resource,parentResource,previousSibling) | 通知移动资源 | |
通知更改 | updateLink(task,property,value) | 通知修改链接 | |
通知更改 | addLink(sucTask,preTask,type) | 通知添加链接 | |
通知更改 | deleteLink(link) | 通知删除链接 | |
通知更改 | updateAssignment(task,property,value) | 通知修改资源分配 | |
通知更改 | addAssignment(task,resource,unit) | 通知添加资源分配 | |
通知更改 | deleteAssignment(assignment) | 通知删除资源分配 |
以上就是目前数据适配器支持的接口列表,这些接口是很细化的,这样的细化可能会一定程度上增加实现的难度,不过却保证了结构的清晰性和接口的灵活性。
到这里,我们已经了解了向日葵甘特图的数据适配器的机制是非常灵活的,虽然现在仅仅支持SFDataProject(兼容Project的XML格式的适配器)和SFDataXml(在SFDataProject基础上进行分块加载优化后的适配器)这两种基于XML的格式,实际上,完全不必一定是XML,你想要实现什么格式都是可以接收的,例如,我们来实现一个数据适配器,这个适配器实现一个这样的数据:2009年全年,每月作为一个概要任务,每天作为一个任务,这个范例实现的数据比较简单,也没有涉及到资源和链接,也没有接收更改的通知,不过本来仅仅是用来演示如何自定义数据适配器。
了解数据适配器的原理有助于为甘特图带来更好的体验和性能,不过大部分情况下,用户都是直接使用SFDataProject和SFDataXml完成自己的项目,在下面的文章之中,我们将介绍SFDataProject和SFDataXml的实现和使用。