GXT之旅:第六章:Templates(1)——Template(1)

第六章:Templates

本章我们要了解Templates,以及学习他们是如何方便我们去自定义数据的格式化和显示。我们也会详细了解XTemplates的丰富功能

本章,我们会涉及到如下GXt功能集

  • Template
  • XTemplate
  • RowExpander
  • ListView
  • ModelProcessor
  • CheckBoxListView
之前的章节,我们学习了data-backed components 使用ModelData objects 如何自动的加载数据的。我们是通过指定其使用ModelData里面的某一列,作为显示内容。但是如果我们希望显示的内容不仅仅是一列,我们要怎么办?比如,如果我们有一个ModelData对象,里面有两列内容——first name和last name,但是我们希望显示的时候是full name(first name+last name)。

当然GXT会想到这样的问题,并且提供了连个解决方案。第一:ModelProcessor可以预加工ModelData,定义出一个新的列(以后会讲到闭嘴)。第二种就是使用Template。

首先,我们要做一些准备工作,在Feed和Item类里面加入更多的fields,并在后端的server方法里面灌入数据——以供给Template使用。

  • Feed类中,加入两个新的fields:imageUrl,存储图片的url;items用来存储Item集合。当然别忘了setter和getter方法
private String imageUrl;
private List<Item> items = new ArrayList<Item>();
  • Item类加入publication和thumbnailUrl。因为是直接继承的BaseModel,所以注意getter和setter方法的书写:
package com.danielvaughan.rssreader.shared.model;

import java.util.Date;

import com.extjs.gxt.ui.client.data.BaseModel;

@SuppressWarnings("serial")
public class Item extends BaseModel {

	public Item() {

	}

	public String getCategory() {
		return get("category");
	}

	public String getDescription() {
		return get("description");
	}

	public String getLink() {
		return get("link");
	}

	public Date getPubDate() {
		return get("pubDate");
	}

	public String getThumbnailUrl() {
		return get("thumbnailUrl");
	}

	public String getTitle() {
		return get("title");
	}

	public void setCategory(String category) {
		set("category", category);
	}

	public void setDescription(String description) {
		set("description", description);
	}

	public void setLink(String link) {
		set("link", link);
	}

	public void setPubDate(Date pubDate) {
		set("pubDate", pubDate);
	}

	public void setThumbnailUrl(String thumbnailUrl) {
		set("thumbnailUrl", thumbnailUrl);
	}

	public void setTitle(String title) {
		set("title", title);
	}
}
  • FeedService接口里修改原来无参数的loadFeedList()方法,为
List<Feed> loadFeedList(boolean loadItems);
  • 别忘了在FeedServiceAsync修改对应的回调方法
void loadFeedList(boolean loadItems, AsyncCallback<List<Feed>>
callback);
  • FeedServiceImpl类里,通过修改loadFeedList()为loadFeedList(boolean loadItems),实现其抽象方法。
	@Override
	public List<Feed> loadFeedList(boolean loadItems)) {
		feeds.clear();
		Set<String> feedUrls = persistence.loadFeedList();
		for (String feedUrl : feedUrls) {
			feeds.put(feedUrl, loadFeed(feedUrl,loadItems)));
		}
		return new ArrayList<Feed>(feeds.values());
	}
  • 修改FeedServiceImpl.loadFeed方法,加入新的loadItems参数。具体实现如下:
private Feed loadFeed(String feedUrl, boolean loadItems) {
		Feed feed = new Feed(feedUrl);
		try {
			SAXBuilder parser = new SAXBuilder();
			Document document = parser.build(new URL(feedUrl));
			Element eleRoot = document.getRootElement();
			Element eleChannel = eleRoot.getChild("channel");
			feed.setTitle(eleChannel.getChildText("title"));
			feed.setDescription(eleChannel.getChildText("description"));
			feed.setLink(eleChannel.getChildText("link"));
			Element eleImage = eleChannel.getChild("image");
			feed.setImageUrl("");
			if (eleImage != null) {
				Element eleUrl = eleImage.getChild("url");
				if (eleUrl != null) {
					feed.setImageUrl(eleUrl.getText());
				}
			}
			if (loadItems) {
				feed.setItems(loadItems(feedUrl));
			}
			return feed;
		} catch (IOException e) {
			LOGGER.log(Level.SEVERE, "IO Error loading feed", e);
			return feed;
		} catch (JDOMException e) {
			LOGGER.log(Level.SEVERE, "Error parsing feed", e);
			return feed;
		}
	}
  • 牵扯到引用loadFeed方法的相关方法修改。
@Override
	public void addExistingFeed(String feedUrl) {
		Feed loadResult = loadFeed(feedUrl, false);
		if (loadResult.getTitle() != null) {
			feeds.put(feedUrl, loadResult);
			persistence.saveFeedList(feeds.keySet());
		}
	}
  • 相应的loadItems方法也要修改,
@Override
	@SuppressWarnings("unchecked")
	public List<Item> loadItems(String feedUrl) {
		List<Item> items = new ArrayList<Item>();
		try {
			SAXBuilder parser = new SAXBuilder();
			Document document = parser.build(new URL(feedUrl));
			Element eleRoot = document.getRootElement();
			Element eleChannel = eleRoot.getChild("channel");
			List<Element> itemElements = eleChannel.getChildren("item");
			for (Element eleItem : itemElements) {
				Item item = new Item();
				item.setTitle(eleItem.getChildText("title"));
				item.setDescription(eleItem.getChildText("description"));
				item.setLink(eleItem.getChildText("link"));
				item.setCategory(eleItem.getChildText("category"));
				Namespace ns = Namespace.getNamespace("media",
						"http://search.yahoo.com/mrss/");
				Element eleThumbnail = eleItem.getChild("thumbnail", ns);
				if (eleThumbnail != null) {
					item.setThumbnailUrl(eleThumbnail.getAttributeValue("url"));
				}
				String pubDateStr = eleItem.getChildText("pubDate");
				if (pubDateStr != null) {
					try {
						DateFormat df = new SimpleDateFormat(
								"EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z");
						item.setPubDate(df.parse(pubDateStr));
					} catch (ParseException e) {
						item.setPubDate(null);
					}
				}
				items.add(item);
			}
			return items;
		} catch (IOException e) {
			e.printStackTrace();
			return items;

		} catch (JDOMException e) {
			e.printStackTrace();
			return items;
		}
	}
  • 最后,在FeedList的onRender方法里,修改为新的service方调用
protected void load(Object loadConfig, AsyncCallback<List<Feed>>
callback) {
feedService.loadFeedList(false, callback);
}
  • 目前为止,准备工作已经完成,下一章会在此数据结构的基础之上使用Template
  • 修改后完整的FeedServiceImpl类如下:
package com.danielvaughan.rssreader.server.services;

import java.io.IOException;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;

import com.danielvaughan.rssreader.client.services.FeedService;
import com.danielvaughan.rssreader.server.utils.FilePersistence;
import com.danielvaughan.rssreader.server.utils.Persistence;
import com.danielvaughan.rssreader.shared.model.Category;
import com.danielvaughan.rssreader.shared.model.Feed;
import com.danielvaughan.rssreader.shared.model.Item;
import com.extjs.gxt.ui.client.data.BasePagingLoadResult;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.google.gwt.dev.util.collect.HashMap;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class FeedServiceImpl extends RemoteServiceServlet implements
		FeedService {

	private final static Logger LOGGER = Logger.getLogger(FeedServiceImpl.class
			.getName());

	private Map<String, Feed> feeds = new HashMap<String, Feed>();

	private final Persistence persistence = new FilePersistence();

	@Override
	public void addExistingFeed(String feedUrl) {
		Feed loadResult = loadFeed(feedUrl, false);
		if (loadResult.getTitle() != null) {
			feeds.put(feedUrl, loadResult);
			persistence.saveFeedList(feeds.keySet());
		}
	}

	@Override
	public Feed createNewFeed() {
		UUID uuid = UUID.randomUUID();
		return new Feed(uuid.toString());
	}

	private PagingLoadResult<Item> getPagingLoadResult(List<Item> items,
			PagingLoadConfig config) {
		List<Item> pageItems = new ArrayList<Item>();
		int offset = config.getOffset();
		int limit = items.size();
		if (config.getLimit() > 0) {
			limit = Math.min(offset + config.getLimit(), limit);
		}
		for (int i = config.getOffset(); i < limit; i++) {
			pageItems.add(items.get(i));
		}
		return new BasePagingLoadResult<Item>(pageItems, offset, items.size());

	}

	@Override
	public List<ModelData> loadCategorisedItems(String feedUrl,
			Category category) {
		List<Item> items = loadItems(feedUrl);
		Map<String, List<Item>> categorisedItems = new HashMap<String, List<Item>>();
		for (Item item : items) {
			String itemCategoryStr = item.getCategory();
			if (itemCategoryStr == null) {
				itemCategoryStr = "Uncategorised";
			}
			List<Item> categoryItems = categorisedItems.get(itemCategoryStr);
			if (categoryItems == null) {
				categoryItems = new ArrayList<Item>();
			}
			categoryItems.add(item);
			categorisedItems.put(itemCategoryStr, categoryItems);
		}
		if (category == null) {
			List<ModelData> categoryList = new ArrayList<ModelData>();
			for (String key : categorisedItems.keySet()) {
				categoryList.add(new Category(key));
			}
			return categoryList;
		} else {
			return new ArrayList<ModelData>(categorisedItems.get(category
					.getTitle()));
		}
	}

	private Feed loadFeed(String feedUrl, boolean loadItems) {
		Feed feed = new Feed(feedUrl);
		try {
			SAXBuilder parser = new SAXBuilder();
			Document document = parser.build(new URL(feedUrl));
			Element eleRoot = document.getRootElement();
			Element eleChannel = eleRoot.getChild("channel");
			feed.setTitle(eleChannel.getChildText("title"));
			feed.setDescription(eleChannel.getChildText("description"));
			feed.setLink(eleChannel.getChildText("link"));
			Element eleImage = eleChannel.getChild("image");
			feed.setImageUrl("");
			if (eleImage != null) {
				Element eleUrl = eleImage.getChild("url");
				if (eleUrl != null) {
					feed.setImageUrl(eleUrl.getText());
				}
			}
			if (loadItems) {
				feed.setItems(loadItems(feedUrl));
			}
			return feed;
		} catch (IOException e) {
			LOGGER.log(Level.SEVERE, "IO Error loading feed", e);
			return feed;
		} catch (JDOMException e) {
			LOGGER.log(Level.SEVERE, "Error parsing feed", e);
			return feed;
		}
	}

	@Override
	public List<Feed> loadFeedList(boolean loadItems) {
		feeds.clear();
		Set<String> feedUrls = persistence.loadFeedList();
		for (String feedUrl : feedUrls) {
			feeds.put(feedUrl, loadFeed(feedUrl, loadItems));
		}
		return new ArrayList<Feed>(feeds.values());
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Item> loadItems(String feedUrl) {
		List<Item> items = new ArrayList<Item>();
		try {
			SAXBuilder parser = new SAXBuilder();
			Document document = parser.build(new URL(feedUrl));
			Element eleRoot = document.getRootElement();
			Element eleChannel = eleRoot.getChild("channel");
			List<Element> itemElements = eleChannel.getChildren("item");
			for (Element eleItem : itemElements) {
				Item item = new Item();
				item.setTitle(eleItem.getChildText("title"));
				item.setDescription(eleItem.getChildText("description"));
				item.setLink(eleItem.getChildText("link"));
				item.setCategory(eleItem.getChildText("category"));
				Namespace ns = Namespace.getNamespace("media",
						"http://search.yahoo.com/mrss/");
				Element eleThumbnail = eleItem.getChild("thumbnail", ns);
				if (eleThumbnail != null) {
					item.setThumbnailUrl(eleThumbnail.getAttributeValue("url"));
				}
				String pubDateStr = eleItem.getChildText("pubDate");
				if (pubDateStr != null) {
					try {
						DateFormat df = new SimpleDateFormat(
								"EEE', 'dd' 'MMM' 'yyyy' 'HH:mm:ss' 'Z");
						item.setPubDate(df.parse(pubDateStr));
					} catch (ParseException e) {
						item.setPubDate(null);
					}
				}
				items.add(item);
			}
			return items;
		} catch (IOException e) {
			e.printStackTrace();
			return items;

		} catch (JDOMException e) {
			e.printStackTrace();
			return items;
		}
	}

	@Override
	public PagingLoadResult<Item> loadItems(String feedUrl,
			PagingLoadConfig config) {
		List<Item> items = loadItems(feedUrl);
		return getPagingLoadResult(items, config);
	}

	@Override
	public void saveFeed(Feed feed) {
		Element eleRoot = new Element("rss");
		eleRoot.setAttribute(new Attribute("version", "2.0"));

		// Create a document from the feed object
		Document document = new Document(eleRoot);

		Element eleChannel = new Element("channel");
		Element eleTitle = new Element("title");
		Element eleDescription = new Element("description");
		Element eleLink = new Element("link");

		eleTitle.setText(feed.getTitle());
		eleDescription.setText(feed.getDescription());
		eleLink.setText(feed.getLink());

		eleChannel.addContent(eleTitle);
		eleChannel.addContent(eleDescription);
		eleChannel.addContent(eleLink);

		eleRoot.addContent(eleChannel);

		persistence.saveFeedXml(feed.getUuid(), document);
		addExistingFeed(persistence.getUrl(feed.getUuid()));
	}
}






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值