保持同步

我们现在需要保证,当有新的feed添加的时候,feeds列表要正确的更新出来。同时,我们也需要保证,当用户选择了某个feed的tab的时候,相对应于feeds列表中的feed会同步的被选中。

为了实现如上两个要求,我们要创建两个对应的events——一个feed被添加,一个feed tab被选中

  • 在AppEvents类里定义两个新的EventType——FeedAdded,TabSelected
public static final EventType TabSelected = new EventType();
public static final EventType FeedAdded = new EventType();
  • 上面两个事件都属于左侧导航区域应该响应的事件。因此,在NavController类里面注册
public NavController() {
registerEventTypes(AppEvents.Init);
registerEventTypes(AppEvents.FeedAdded);
registerEventTypes(AppEvents.TabSelected);
}


  • 在FeedList类里,将ListField和ListLoader的定义从onRender方法里提出来
private final ListField<BeanModel> feedList = new
ListField<BeanModel>();
private ListLoader<ListLoadResult<BeanModel>> loader;


  • 继续重构,定义一个新的方法reloadFeeds,其功能是负责load真正的数据。
public void reloadFeeds() {
loader.load();
}
  • 定义第二个新方法selectFeed,其功能是,使用参数feed去设置,选中适当的ListField
public void selectFeed(Feed feed) {
BeanModelFactory beanModelFactory = BeanModelLookup.get().getFactory(
feed.getClass());
feedList.setSelection(Arrays.asList(beanModelFactory.createModel(feed)));
}
  • 在NavPanel类里,重构一下其构造函数,将匿名对象new FeedList();提为属性
private FeedList feedList = new FeedList();

public NavPanel() {
setHeading("Navigation");
setLayout(new FitLayout());
initToolbar();
add(feedList);
}
  • 在NavPanel类里,再定义两个新方法——selectFeed,reloadFeeds方法,相同于FeedList类里的方法。
public void reloadFeeds() {
feedList.reloadFeeds();
}

public void selectFeed(Feed feed) {
feedList.selectFeed(feed);
}
  • 在NavView类里,新建onTabSelected方法,通过AppEvent获得其携带的feed,feed用于调用selectFeed方法传入参数。
private void onTabSelected(AppEvent event) {
Feed feed = (Feed) event.getData();
navPanel.selectFeed(feed);
}
  • 继续,在NavView类里,新建onFeedAdded方法,调用NavPanel.reloadFeeds方法
private void onFeedAdded(AppEvent event) {
navPanel.reloadFeeds();
}
  • 在NavView类里,开始修改handleEvent方法,根据事件的类型,调用与之对应的处理方法
@Override
protected void handleEvent(AppEvent event) {
EventType eventType = event.getType();

if (eventType.equals(AppEvents.Init)) {
Dispatcher.forwardEvent(new AppEvent(AppEvents.NavPanelReady,
navPanel));
} else if (eventType.equals(AppEvents.TabSelected)) {
onTabSelected(event);
} else if (eventType.equals(AppEvents.FeedAdded)) {
onFeedAdded(event);
}
}


  • 在LinkFeedPopup类里的addFeed方法里,之前我们通过调用FeedService.addExistingFeed方法来添加一个feed的link。接下来在其onSuccess方法我们触发FeedAdded事件
public void addFeed(final String feedUrl) {
final FeedServiceAsync feedService = Registry
.get(RSSReaderConstants.FEED_SERVICE);
feedService.addExistingFeed(feedUrl, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Info.display("RSS Reader", "Failed to add feed at: " + feedUrl);
}

@Override
public void onSuccess(Void result) {
tfUrl.clear();
Info.display("RSS Reader", "Feed at " + feedUrl
+ " added successfully");
Dispatcher.forwardEvent(AppEvents.FeedAdded);
hide();
}
});
}
  • 类似的,在FeedForm.save方法里,在调用FeedService.saveFeed方法时的onSuccess方法里,加入同样的触发FeedAdded事件
public void save(final Feed feed) {
feed.setTitle(tfTitle.getValue());
feed.setDescription(taDescription.getValue());
feed.setLink(tfLink.getValue());

final FeedServiceAsync feedService = Registry
.get(RSSReaderConstants.FEED_SERVICE);
feedService.saveFeed(feed, new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
Info.display("RSS Reader",
"Failed to save feed: " + feed.getTitle());
}

@Override
public void onSuccess(Void result) {
Info.display("RSS Reader", "Feed " + feed.getTitle()
+ " saved sucessfully");
Dispatcher.forwardEvent(AppEvents.FeedAdded);
}
});

}
  • 最后,在FeedView.onFeedSelected方法里,在现有的Listener内触发TabSelected事件
private void onFeedSelected(AppEvent event) {
final Feed feed = event.getData();
final ItemGrid itemGrid = new ItemGrid(feed);
TabItem tabItem = new TabItem(feed.getTitle());
tabItem.setId(feed.getUuid());
tabItem.setData("feed", feed);
tabItem.add(itemGrid);
tabItem.addListener(Events.Select, new Listener<TabPanelEvent>() {// 选中之后的tab清空item
// selection
@Override
public void handleEvent(TabPanelEvent be) {
itemGrid.resetSelection();
Dispatcher.forwardEvent(new AppEvent(
AppEvents.TabSelected, feed));
}
});
tabItem.setClosable(true);
feedPanel.addTab(tabItem);
}