使用Google Web Toolkit開發RSS閱讀器(上) 文/沈炳宏 ==========程式========= 程式1 projectcreator -eclipse rssreader applicationcreator -eclipse rssreader com.lodgon.ajax.demo1.client.rssreader ==========程式========= ==========程式========= 程式2 RUN!PC Ajax Demo : RSS Reader

RUN!PC Ajax Demo : RSS Reader

… … …
 
==========程式========= ==========程式========= 程式3 ==========程式========= ==========程式========= 程式4 public void onModuleLoad() { RootPanel catPanel = RootPanel.get ("categories"); RootPanel titlePanel = RootPanel.get ("postings"); RootPanel contentPanel = RootPanel.get ("content"); category = new CategoryWidget(this); posting = new PostingsWidget(this, 10); content = new ContentWidget (this); catPanel.add(category); titlePanel.add (posting); contentPanel.add (content); } public PostingsWidget getPosting() { return posting; } public ContentWidget getContent() { return content; } ==========程式========= ==========程式========= 程式5 public class CategoryWidget extends Composite implements ClickListener { private String myCategory = null; private final VerticalPanel outer = new VerticalPanel(); private CategoryCheckBox[] ccb = new CategoryCheckBox[1]; private RssReaderDemo parent = null; public CategoryWidget(RssReaderDemo parent) { initWidget(outer); String cname = getCategory(); … } private String getCategory() { BlogServiceAsync blogService = (BlogServiceAsync) GWT.create(BlogService.class); ServiceDefTarget endpoint = (ServiceDefTarget) blogService; endpoint.setServiceEntryPoint( GWT.getModuleBaseURL() + "/ajax/blogservice"); String answer = "loading"; AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { myCategory = "success"; String[] keyw = (String[]) result; ccb = new CategoryCheckBox[keyw.length]; for (int i = 0; i < keyw.length; i++) { ccb[i] = new CategoryCheckBox(keyw[i], i); ccb[i].setText(keyw[i]); ccb[i].addClickListener(CategoryWidget.this); ccb[i].setChecked(true); ccb[i].setStyleName("table"); outer.add(ccb[i]); } onClick(ccb[0]); } public void onFailure(Throwable caught) { myCategory = "failure"; caught.printStackTrace(); } }; blogService.getCategories(6, callback); return answer; } public void onClick(Widget sender) { HashSet hs = new HashSet(); for (int i = 0; i < ccb.length; i++) { if (ccb[i].isChecked()) { hs.add(ccb[i].getText()); } } parent.getPosting().setKeywords(hs); parent.getPosting().refresh(); } private class CategoryCheckBox extends CheckBox { public final int id; public CategoryCheckBox(String caption, int id) { super(caption); this.id = id}} ==========程式========= ==========程式========= 程式6 public class PostingsWidget extends Composite implements ClickListener { … public PostingsWidget(RssReaderDemo parent, int rows) { … initializeGrid(rows); dp.add(grid, DockPanel.NORTH); getEntries(); } private void initializeGrid(int r) { grid.resize(r, 2); grid.setText(0, 0, “Title”); grid.getCellFormatter().setStyleName( 0, 0, "title header"); grid.setText(0, 1, “Date”); grid.getCellFormatter().setStyleName( 0, 1, "date header"); } private void getEntries() { … AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { entries = (Entry[]) result; showEntries(); } … }; blogService.getEntries(6, callback); } public void refresh() { showEntries(); } private void showEntries() { int num = entries.length; grid.resize(num + 1, 2); int show = 1; for (int row = 0; row < num; row++) { Entry me = entries[row]; if (match(me)) { String title = me.getTitle(); Hyperlink hl = new Hyperlink(title, me.getExternalId()); hl.addClickListener(this); grid.setWidget(show, 0, hl); String date = me.getFormattedDate(); grid.setText(show, 1, date); show++; }}grid.resize(show, 2);} public void setKeywords(HashSet hs) { this.keywords = hs; } private boolean match(Entry e) { String myTags = e.getKeywords(); if (myTags == null) { return false; } Iterator it = keywords.iterator(); while (it.hasNext()) { String s = (String) (it.next()); if (myTags.indexOf(s) > -1) { return true;} } return false; } public void onClick(Widget w) { if (w instanceof Hyperlink) { Hyperlink source = (Hyperlink) w; String target = source.getTargetHistoryToken(); for (int i = 0; i < entries.length; i++) { if (entries[i].getExternalId().equals(target)) { parent.getContent().setHTML( myConstants.getAuthor() +":" + entries[i].getAuthor() + "
" + "Full Article: http://" + entries[i].getExternalId() + "
" + entries[i].getContent()); } }}}} ==========程式========= ==========程式========= 程式7 public class ContentWidget extends Composite { private RssReaderDemo parent; private HTML outer = new HTML(); private DockPanel dp = new DockPanel(); private Label lb = new Label(); public ContentWidget (RssReaderDemo parent) { initWidget(dp); this.parent = parent; outer.setHTML(" "); dp.add(outer, DockPanel.NORTH); } public void setHTML (String h) { outer.setHTML (h); } public String getHTML () { return outer.getHTML(); } } ==========程式========= ==========程式========= 程式8 import com.google.gwt.user.client.rpc.RemoteService; public interface BlogService extends RemoteService { public String[] getCategories (int i); public Entry[] getEntries (int i); } ==========程式========= ==========程式========= 程式9 import com.google.gwt.user.client.rpc.IsSerializable; public class Entry implements IsSerializable { private String title; private String content; private String keywords; private String author; private String externalId; private String summary; private String formattedDate; private long date; public Entry() { } public void setTitle(String v) { this.title = v; } public String getTitle() { return this.title; } public void setContent(String v) { this.content = v; } public String getContent() { return this.content; } public void setSummary(String v) { this.summary = v; } public String getSummary() { return this.summary; } public void setKeywords(String v) { this.keywords = v; } public String getKeywords() { return this.keywords; } public void setAuthor(String v) { this.author = v; } public String getAuthor() { return this.author; } public void setExternalId(String v) { this.externalId = v; } public String getExternalId() { return this.externalId; } public void setFormattedDate(String v) { this.formattedDate = v; } public String getFormattedDate() { return this.formattedDate; } public void setCreationDate(long v) { this.date = v; } public long getCreationDate() { return this.date; } } ==========程式========= ==========程式========= 程式10 interface BlogServiceAsync { public void getCategories (int i, AsyncCallback callback); public void getEntries (int i, AsyncCallback callback); } ==========程式========= ==========程式========= 程式11 public class BlogServiceImpl extends RemoteServiceServlet implements BlogService { private boolean busy = false; private Entry[] entries = new Entry[1]; private HashSet cats = new HashSet(); private final long TIMEOUT = 10 * 1000L; private long lastCrawl = 0L; public BlogServiceImpl() { try { getData(); } catch (Exception e) { e.printStackTrace(); } } private synchronized void getData() throws Exception { RssFeedParser rfp = new RssFeedParser( "http://blog.yam.com/rss20/top20_all.xml"); List l = rfp.getPostings(); entries = new Entry[l.size()]; cats = new HashSet(); Iterator it = l.iterator(); int i = 0; while (it.hasNext()) { entries[i] = (Entry) (it.next()); if (entries[i].getKeywords() != null) { StringTokenizer st = new StringTokenizer( entries[i].getKeywords(),","); while (st.hasMoreTokens()) { String c1 = (String) st.nextToken(); cats.add(c1); } } i++; } lastCrawl = System.currentTimeMillis(); } public String[] getCategories(int catid) { if (System.currentTimeMillis() > (lastCrawl + TIMEOUT)) { try { getData(); } catch (Exception e) { e.printStackTrace(); } } String[] answer = new String[cats.size()]; Iterator it = cats.iterator(); int i = 0; while (it.hasNext()) { answer[i] = (String) it.next(); i++; } return answer; } public Entry[] getEntries(int i) { if (System.currentTimeMillis() > (lastCrawl + TIMEOUT)) { try { getData(); } catch (Exception e) { e.printStackTrace(); } } return entries; } ==========程式=========