使用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;
}
==========程式=========