GXT之旅:第四章:Data与Components(4)——远程数据(remote data)


使用remote data

stores的数据来源不单单可以从client-side获得(就是从Registry里获得),也可以通过调用远程数据来获得。对于远程数据的加载和处理工作,GXT已经提供了轻巧方便的手段。她支持通过HTTP协议来检索XML或者JSON格式的数据,或者直接通过GWT RPC来检索到objects对象。对于不同的数据源,GXT提供了相应的机制。如果有必要的话,会把原始的数据转换成ModelData并且自动的放入store里。

对于远程数据的处理过程,会涉及到几个components(非可视化组件)。他们各尽其责,协同工作完成远程数据的检索和加工等操作。

  • DataProxy—负责从数据源检索出原始的数据
  • DataReader—将检索出的原始数据转换成client-side可用的ModelData
  • Loader—将转换好的ModelData自动的加载到store里,给data-backed components使用


这个几个components的相互作用,协同工作图解如下:


DataProxy 接口

DataProxy就是用来从数据源检索原始数据的。根据不同的协议类型,有具体的proxy代理实现类,但他们是都是实现了GXT提供的DataProxy接口的。下面就大致介绍一下具体的实现类

DataProxy 描述
HttpProxy 通过GWT的Requestbuilder传输同一个server的数据,读取XML或JSON格式的数据。
MemoryProxy 简单的通过指定的构造函数传递数据
PagingModelMemoryProxy 类似MemoryProxy,但是支持在从memory中读取数据时分页
RpcProxy 使用GWT RPC来检索数据,允许其过程中通过loader将javabean数据转换
ScriptTagProxy 通过一个URL来检索其返回的数据,其URL可以是别的域名,而不是自己服务器运行的域名。但是只支持JSON
一旦我们使用DataProxy检索出来数据,其原始的数据不是ModelData格式的时候,我们就需要使用DataReader给原始的数据转换成ModelData,这样一来,转换后的数据才可以被放入Store,供给components使用。

DataReader 接口

DataReader的作用是用来翻译原始数据,将其转换成ModelData 类型的object。针对不用类型的原始数据,有对应的具体Reader,但是他们都是实现GXT提供的DataReader接口。一个DataReader的返回值可能是下面列表当中的一个:

  • ModelData类型的对象集合
  • 一个实现了ListLoadResult接口的object——在ListLoadResult接口里有个一getData()方法用来返回ModelData object的
  • 一个PagingLoadResult object——PagingLoadResult 扩展了ListLoadResult接口,加入了分页的功能,因此返回一组数据的子集。

下面是一组列表,介绍不同类型的具体的DataReader实现类


DataReader 输入数据类型 转换时,使用的工具类 输入数据类型 何时使用此Reader
ModelReader ModelData 输入的已经是ModelData,不需要何人转换,只要放入到ListLoadResult即可 ListLoadResult 当加载的原始数据已经继承BeanModel
BeanModelReader JavaBean的集合 BeanModelFactory ListLoadResult 当加载的原始数据是普通的javabean,需要使用他将其转换成BeanModel
JsonReader JSON数据 ModelType定义 ModelData结果集 当原始数据是Json类型时
JsonLoadResult
Reader
JSON数据 ModelType定义 ListLoadResult 当原始数据是Json类型时
JsonPagingLoadResult
Reader
JSON数据 ModelType定义 PagingLoadResult 当原始数据是Json类型时
XmlReader XML数据 ModelType定义 ModelData结果集 当原始数据是xml类型时
XmlLoadResultReader XML数据 ModelType定义 ListLoadResult 当原始数据是xml类型时
XmlPagingLoadResult
Reader
XML数据 ModelType定义 PagingLoadResult 当原始数据是xml类型时
当然还有TreeModelReader用来转换树结构的数据的,以后会讲到。

上面的列表大家会注意到“ModelType定义”这句话。ModelType是在Reader在进行转换的时候会用到的类。


ModelType的使用

ModelType是用来定义原始数据的结构类型的。定要其原始数据的结构之后,reader就会根据此结构进行读取转换。

拿XML类型的数据来说,其结构比如:



 
  The best book in the world
 
 
  The worst book in the world
 

那么就上面的结构,ModelType应该有如下定义:

final ModelType modelType = new ModelType();
modelType.setRoot("books");
modelType.setRecordName("book");
modelType.addField("title");

跟节点是books,book是记录集,title是具体的一个field属性。


ModelType当然也支持定义Json数据类型的结构。如下的Json数据,ModelType的定义同上

{
"books": [
    {
        "book": {
            "title": "The best book in the world"
        },
        "book": {
            "title": "The worst book in the world"
        }
    }
]
}

Loader接口

  1. 当DataProxy将原始数据获得,
  2. 数据被DataReader转换成ModelData之后
  3. 就需要使用Loaders,将ModelData装入Store

Loader是所有接口根接口,与之对应的BaseLoader是所有抽象类的根抽象类。当然BaseLoader实现了Loader接口。请看下图:


Loader一共就分两类:一个是List一个是Tree。打开源码一看便知之前的关系。

Loaders可以在数据加载的时候,将其排序,可以功过setSortField,setSortDir方法进行设置,当然也可以通过LoadConfig对象来设置。


LoadConfig

LoadConfig配置了数据是如何被Loader到store的。Loadconfig接口有一系列的实现类(BaseGroupingLoadConfigBasePagingLoadConfig),看名称就猜到大概意思这里就不详细介绍了。我自己也没怎么研究。。。


重新屡屡思路

  1. GXT所能使用的classes必须要直接或间接的实现了ModelData接口,才可以放入Store里
  2. Store里面存储的ModelData,其实是充当的client-side的缓存层,Data-backed components直接使用的是Store
  3. 用DataProxy将远程的原始数据获得
  4. ModelType定义了远程数据的结构体
  5. DataReader根据ModelType的描述,把原始的数据转换成ModelData
  6. Loader按照DataProxy和DataReader的定义,一气呵成,执行之后将数据装入Store。
  7. Loadconfig的定义告诉Loader对ModelData数据如何排序,分组,分页等配置。


将上面提到的所有内容应用到RSSReader项目里

  • 编辑com.danielvaughan.rssreader.client.listsFeedList类的onRender方法
package com.danielvaughan.rssreader.client.lists;

import java.util.List;

import com.danielvaughan.rssreader.client.RSSReaderConstants;
import com.danielvaughan.rssreader.client.services.FeedServiceAsync;
import com.danielvaughan.rssreader.shared.model.Feed;
import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelReader;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.form.ListField;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class FeedList extends LayoutContainer {

	public FeedList() {
		setLayout(new FitLayout());
	}

	@Override
	protected void onRender(Element parent, int index) {
		super.onRender(parent, index);
		final ListField feedList = new ListField();
		//0:从Registry里获得Service
		final FeedServiceAsync feedService = (FeedServiceAsync) Registry
				.get(RSSReaderConstants.FEED_SERVICE);
		//1:定义proxy在load方法里嗲用Serivce里的方法
		RpcProxy> proxy = new RpcProxy>() {
			@Override
			protected void load(Object loadConfig,
					AsyncCallback> callback) {
				feedService.loadFeedList(callback);

			}
		};
		//2:定义Reader
		BeanModelReader reader = new BeanModelReader();
		//3:将proxy和reader传入,定义loader
		ListLoader> loader = new BaseListLoader>(
				proxy, reader);
		//4:传入loader,生成store,此时还没有load数据
		ListStore feedStore = new ListStore(loader);
		//5:将stroe绑定到data-backed component身上
		feedList.setStore(feedStore);
		feedList.setDisplayField("title");
		//6:真正的load数据,load成功之后,data-backed component会自动的显示出来。
		loader.load();

		add(feedList);
	}
}

你可能感兴趣的:(GWT/GXT,GXT之旅)