Registry
GXT提供一个Registry类。他就像HashMap,可以在应用程序的client端内随意使用它。他就像一个载体,穿梭在client端的任何类之间,用于传递数据。
Registry存储services
Registry就是用来存储数据的。数据可以是多种多样的,除了基本的list之外,他可以存储services——当services被创建的时候,就被放入Registry内,然后可以在client端的任何位置,调用registry,取出services,通过services调用server端的代码,大致套路就是这样了 。 对于RSSReader项目目前而言,registry要存放的service是FeedServiceAsync,当从registry中取出FeedServiceAsync(services) ,去调用FeedServiceAsync里的方法,那么就会调用server端的FeedServiceImpl类中对应的具体实现方法。- 首先,要创建一个const类,用来定义放入Registry中的keys——RSSReaderConstants
package com.danielvaughan.rssreader.client;
public class RSSReaderConstants {
public static final String FEED_SERVICE = "feedService";
}
- 要在程序最开始的时候,就把services注册到Registry内。所以编辑RSSReader类的onModuleLoad()方法,加入如下代码:
Registry.register(RSSReaderConstants.FEED_SERVICE,
GWT.create(FeedService.class));
- 注意:GWT.create(FeedService.class)的含义是,通过FeedService.class,得到了FeedServiceAsync.class。
- 修改RssNavigationPanel类的createNewFeedWindow(),加入从Registry内获得FeedServiceAsync类的代码:
private void createNewFeedWindow()
{
final FeedServiceAsync feedService =
Registry.get(RSSReaderConstants.FEED_SERVICE);
}
- 得到了FeedServiceAsync,下面就要通过GWT的RPC去调用server端了(FeedServiceImpl)。完整的在createNewFeedWindow()方法内,调用RPC的代码如下:
private void createNewFeedWindow() {
final FeedServiceAsync feedService = Registry
.get(RSSReaderConstants.FEED_SERVICE);
feedService.createNewFeed(new AsyncCallback<Feed>() {
@Override
public void onFailure(Throwable caught) {
Info.display("RSSReader", "Unable to create a new feed");
}
@Override
public void onSuccess(Feed feed) {
final Window newFeedWindow = new FeedWindow(feed);
newFeedWindow.show();
}
});
}
- 注意,上面代码的执行流程是:首先调用FeedServiceImpl.createNewFeed()方法。当执行完毕之后,成功了就会回调onSuccess(),反之失败了,就会回调onFailure()方法。注意此过程是异步的(asynchronous)。
- 因此整个过程实现了,当点击create feed button 的时候,会调用createNewFeedWindow()方法,去请求一个有ID主键的Feed 对象。如果Feed对象成功返回之后,新建一个FeedWindow窗口,同时传入刚刚成功返回的feed,然后显示FeedWindow窗口。Registry在此过程中,提供了调用RPC的feedService。
保存Feed
接下来,在FeedForm类中要新建save()方法,用来接收用户录入的信息,存储到先前通过RPC成功返回的feed中去。当然还得添加一个button用来验证表单,当验证通过之后,调用save()方法。
- 在FeedForm类中要新建save(),用来接收用户录入的信息:
public void save(final Feed feed) {
feed.setTitle(tfTitle.getValue());
feed.setDescription(taDescription.getValue());
feed.setLink(tfLink.getValue());
}
- 在FeedWindow类中加入Save button。当form验证通过之后,调用FeedForm类中save()方法。
package com.danielvaughan.rssreader.client.windows;
import com.danielvaughan.rssreader.client.forms.FeedForm;
import com.danielvaughan.rssreader.shared.model.Feed;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.google.gwt.user.client.Element;
public class FeedWindow extends Window {
private final FeedForm feedForm = new FeedForm();
public FeedWindow(final Feed feed) {
setHeading("Feed");
setWidth(350);
setHeight(200);
setResizable(false);
setLayout(new FitLayout());
final Button btnSave = new Button("Save");
btnSave.setIconStyle("save");
btnSave.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
btnSave.setEnabled(false);
if (feedForm.isValid()) {
hide(btnSave);
feedForm.save(feed);
} else {
btnSave.setEnabled(true);
}
}
});
addButton(btnSave);
}
@Override
protected void onRender(Element parent, int pos) {
super.onRender(parent, pos);
add(feedForm);
}
}
- 当然要给Save button美化一下。
.save {
background: url(gxt/images/icons/disk.png) no-repeat center
left
!important;
}
- 运行之后的效果:
- 当点击save button 之后,用户录入的信息,就会存入到feed对象中。填充好feed之后的持久化操作,下一节会提到。