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
ModelReaderModelData输入的已经是ModelData,不需要何人转换,只要放入到ListLoadResult即可ListLoadResult当加载的原始数据已经继承BeanModel
BeanModelReaderJavaBean的集合BeanModelFactoryListLoadResult当加载的原始数据是普通的javabean,需要使用他将其转换成BeanModel
JsonReaderJSON数据ModelType定义ModelData结果集当原始数据是Json类型时
JsonLoadResult
Reader
JSON数据ModelType定义ListLoadResult当原始数据是Json类型时
JsonPagingLoadResult
Reader
JSON数据ModelType定义PagingLoadResult当原始数据是Json类型时
XmlReaderXML数据ModelType定义ModelData结果集当原始数据是xml类型时
XmlLoadResultReaderXML数据ModelType定义ListLoadResult当原始数据是xml类型时
XmlPagingLoadResult
Reader
XML数据ModelType定义PagingLoadResult当原始数据是xml类型时
当然还有TreeModelReader用来转换树结构的数据的,以后会讲到。

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


ModelType的使用

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

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


<books>
 <book>
  <title>The best book in the world</title>
 </book>
 <book>
  <title>The worst book in the world</title>
 </book>
</books>

那么就上面的结构,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<BeanModel> feedList = new ListField<BeanModel>();
		//0:从Registry里获得Service
		final FeedServiceAsync feedService = (FeedServiceAsync) Registry
				.get(RSSReaderConstants.FEED_SERVICE);
		//1:定义proxy在load方法里嗲用Serivce里的方法
		RpcProxy<List<Feed>> proxy = new RpcProxy<List<Feed>>() {
			@Override
			protected void load(Object loadConfig,
					AsyncCallback<List<Feed>> callback) {
				feedService.loadFeedList(callback);

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

		add(feedList);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值