RSS实例
2010-08-06 00:25
218 查看
57、RSS实例
SAX解析XML基本知识:
/article/7458611.html
RSS也叫聚合RSS是在线共享内容的一种简易方式 ,RSS其实就是通过解析XML文件,把有效信息显示给用户的一种服务。
总体设计:
1、通过数据库存储RSS站点
2、默认提供一些站点,用户可以自己添加站点
3、在管理模式下可以编辑或删除站点(目前只完成删除)
首先定义布局:
1、入口程序继承ListActivity,这样可以不需要在onCreate方法中设置setContentView()。
2、在onListItemClick()中添加点击ListView时的事件:启动另一个Activity,ShowRSSItems用来显示对用的RSS条目。
3、在ShowRSSItems中用ListView来进行显示,点击每个条目之后进入另一个Activity,ShowDescription,用WebView来显示内容,并放置一个返回按钮。
4、数据库的初始化在SSData extends SQLiteOpenHelper中的onCreate完成,即建立表和初始化数据。注意,程序在打包发布的时候,数据库里的内容是会被清除的,如果在MainActivity中进行数据的初始化,那么在调试程序的时候当数据库中已经有数据时必须将这些代码注释掉。但一旦打包发布后,数据库里的内容就消失了,所以在RSSData中进行。
5、在管理模式中,ListView每一个项的右边都有一个删除的图标,用户点击这个图标可以进行删除操作,这个图标其实是一个设置了背景属性为一张png图标的Button。这里参考了网上的布局方法,自定义了Adapter,它继承了BaseAdapter,主要是重写一个叫getView()的方法:
6、上面用到了布局文件list_item_model.xml,而不是用系统的布局,至于如何让ListView的每一行显示两小行数据(一个标题一个链接),则需要灵活设置布局文件以及字体的大小:
7、如何知道每个按钮是跟ListView中的每一项对应起来的呢,这里用到了按钮的setContentDescription(String desc)方法,在初始化每一个按钮的时候变给它设置了setContentDescription,传入每一URL_List的ID以及title,可以用‘/’隔开,取数据的时候再根据‘/’来进行分割,如:
8、添加站点
添加站点的布局倒花费了不少时间,主要是对布局的不熟悉,总结一下心得:
1、让TextView的文字居中显示:
可以在该TextView外面再加多一层RelativeLayout,然后让TextView的属性如下所示:
主要是
android:layout_width="wrap_content" 和
android:layout_centerInParent="true"
2、TableLayout中 android:stretchColumns="0,1"是然TableRow中的第一列跟第二列自动适应并填满。
9、还有一点很重要的就是ListView对数据的刷新:
不要在onCreate中进行刷新操作,因为onCreate只是在第一个建立该Actiivity时才运行一次的。那么可以在onResume和onPause()中进行刷新操作:
10、程序的菜单设计在res/menu中进行设计比较简单:
下面是对应的相应事件:
11、最后是程序的核心咯,也就是如何用SAX来解析XML文件,这里分四步走:
1、建立一个类似JavaBean的类(RSSItem.java),用于描述一个XML文件中的标签,如:
public static final String TITLE = "title";
public static final String PUBDATE = "pubdate";
private String title = null;
private String description = null;
private String link = null;
private String category = null;
private String pubdate = null;
然后给出这些字段的get和set方法。
2、建立一个与XML文件对应的类(RSSView.java):
3、第三步是最重要的一步,即定义一个Handler,继承DefaultHandler:
SAX解析XML基本知识:
/article/7458611.html
RSS也叫聚合RSS是在线共享内容的一种简易方式 ,RSS其实就是通过解析XML文件,把有效信息显示给用户的一种服务。
总体设计:
1、通过数据库存储RSS站点
2、默认提供一些站点,用户可以自己添加站点
3、在管理模式下可以编辑或删除站点(目前只完成删除)
首先定义布局:
1、入口程序继承ListActivity,这样可以不需要在onCreate方法中设置setContentView()。
2、在onListItemClick()中添加点击ListView时的事件:启动另一个Activity,ShowRSSItems用来显示对用的RSS条目。
3、在ShowRSSItems中用ListView来进行显示,点击每个条目之后进入另一个Activity,ShowDescription,用WebView来显示内容,并放置一个返回按钮。
4、数据库的初始化在SSData extends SQLiteOpenHelper中的onCreate完成,即建立表和初始化数据。注意,程序在打包发布的时候,数据库里的内容是会被清除的,如果在MainActivity中进行数据的初始化,那么在调试程序的时候当数据库中已经有数据时必须将这些代码注释掉。但一旦打包发布后,数据库里的内容就消失了,所以在RSSData中进行。
5、在管理模式中,ListView每一个项的右边都有一个删除的图标,用户点击这个图标可以进行删除操作,这个图标其实是一个设置了背景属性为一张png图标的Button。这里参考了网上的布局方法,自定义了Adapter,它继承了BaseAdapter,主要是重写一个叫getView()的方法:
@Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item_model, null); holder.img = (ImageView) convertView.findViewById(R.id.img); holder.title = (TextView) convertView.findViewById(R.id.title); holder.link = (TextView) convertView.findViewById(R.id.link); holder.moreBtn = (Button) convertView .findViewById(R.id.list_but); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.title.setText((String) URL_List.get(position) .get(RSS_T_L[0])); holder.link .setText((String) URL_List.get(position).get(RSS_T_L[1])); String rid = URL_List.get(position).get(RSSID).toString(); holder.moreBtn.setContentDescription(rid + "/" + (String) URL_List.get(position).get(RSS_T_L[0])); holder.moreBtn.setBackgroundResource(R.drawable.del3); holder.moreBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button current = (Button) v; String desc = current.getContentDescription().toString(); String desc_arr[] = desc.split("/"); showInfo(desc_arr[0], desc_arr[1]); } }); return convertView; }
6、上面用到了布局文件list_item_model.xml,而不是用系统的布局,至于如何让ListView的每一行显示两小行数据(一个标题一个链接),则需要灵活设置布局文件以及字体的大小:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px"/> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="22dip" /> <TextView android:id="@+id/link" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="13dip" /> </LinearLayout> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/list_but" android:layout_width="24px" android:layout_height="24px" android:focusable="false" android:layout_gravity="center|right" android:layout_alignParentRight="true" /> </RelativeLayout> </LinearLayout>
7、如何知道每个按钮是跟ListView中的每一项对应起来的呢,这里用到了按钮的setContentDescription(String desc)方法,在初始化每一个按钮的时候变给它设置了setContentDescription,传入每一URL_List的ID以及title,可以用‘/’隔开,取数据的时候再根据‘/’来进行分割,如:
holder.moreBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button current = (Button) v; String desc = current.getContentDescription().toString(); String desc_arr[] = desc.split("/"); showInfo(desc_arr[0], desc_arr[1]); } });
8、添加站点
添加站点的布局倒花费了不少时间,主要是对布局的不熟悉,总结一下心得:
1、让TextView的文字居中显示:
可以在该TextView外面再加多一层RelativeLayout,然后让TextView的属性如下所示:
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/add_rss" android:textStyle="bold" android:textSize="22dip" android:layout_centerInParent="true" android:layout_margin="30dip"/>
主要是
android:layout_width="wrap_content" 和
android:layout_centerInParent="true"
2、TableLayout中 android:stretchColumns="0,1"是然TableRow中的第一列跟第二列自动适应并填满。
<TableLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:stretchColumns="0,1" android:layout_margin="15dip" > <TableRow> <Button android:id="@+id/but_add" android:text="@string/but_add"/> <Button android:id="@+id/but_cancle" android:text="@string/but_cancle" /> </TableRow> </TableLayout>
9、还有一点很重要的就是ListView对数据的刷新:
不要在onCreate中进行刷新操作,因为onCreate只是在第一个建立该Actiivity时才运行一次的。那么可以在onResume和onPause()中进行刷新操作:
@Override protected void onResume() { URL_List = new ArrayList<Map<String, Object>>(); SQLiteDatabase sdb = rd.getReadableDatabase(); URL_List = showRSSList(sdb); // showRSSList(sdb); // adapter.notifyDataSetChanged(); // itemlist.setAdapter(adapter); MyAdapter adapter = new MyAdapter(this); setListAdapter(adapter); super.onResume(); } @Override protected void onPause() { /* * 网上说下面这种方法可以奏效,不过试了没用,可能用法有些不正确,故采用了重新调用 * showRSSList(),不过要让适配器的第二个参数(即这里的URL_List)清空,否则新内容 会追加到ListView后面 */ // adapter.notifyDataSetChanged(); // itemlist.setAdapter(adapter); URL_List = new ArrayList<Map<String, Object>>(); SQLiteDatabase sdb = rd.getReadableDatabase(); URL_List = showRSSList(sdb); // showRSSList(sdb); MyAdapter adapter = new MyAdapter(this); setListAdapter(adapter); super.onPause(); }
10、程序的菜单设计在res/menu中进行设计比较简单:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/add_item" android:title="@string/add_rss" android:icon="@drawable/add"/> <item android:id="@+id/manager" android:title="@string/manager" android:icon="@drawable/manage"/> <item android:id="@+id/flush" android:title="@string/flush" android:icon="@drawable/flush"/> <item android:id="@+id/about" android:title="@string/about" android:icon="@drawable/about"/> </menu>
下面是对应的相应事件:
@Override public boolean onOptionsItemSelected(MenuItem item) { // return super.onOptionsItemSelected(item); switch (item.getItemId()) { case R.id.add_item: this.startActivity(new Intent(this, RSSAddItem.class)); return true; case R.id.manager: // holder.moreBtn.setBackgroundResource(R.drawable.del3); Intent manager = new Intent(this, ManagerModel.class); this.startActivity(manager); // b.putParcelableArrayList("URL_List", URL_List); break; case R.id.about: new AlertDialog.Builder(this).setTitle("关于 MyRSS").setMessage( "MyRSS为您提供了新闻阅读功能,默认提供了人民网九大新闻频道," + "让您轻松掌握具有权威性、及时性、多样性的新闻资讯!您也可以随时增加或删除RSS站点!/n" + "版本:1.1/n作者:天蓝/nQQ:349903386/n有任何疑问请联系我!") .setPositiveButton("确定", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }).show(); break; case R.id.flush: this.onResume(); break; } return false; }
11、最后是程序的核心咯,也就是如何用SAX来解析XML文件,这里分四步走:
1、建立一个类似JavaBean的类(RSSItem.java),用于描述一个XML文件中的标签,如:
public static final String TITLE = "title";
public static final String PUBDATE = "pubdate";
private String title = null;
private String description = null;
private String link = null;
private String category = null;
private String pubdate = null;
然后给出这些字段的get和set方法。
2、建立一个与XML文件对应的类(RSSView.java):
public class RSSView { private String title = null; private String pubdate = null; private int itemcount = 0; private List<RSSItem> itemlist; public RSSView() { itemlist = new Vector(0); } public int addItem(RSSItem item) { itemlist.add(item); itemcount++; return itemcount; } public RSSItem getItem(int location) { return itemlist.get(location); } public List getAllItems() { return itemlist; } public List getAllItemForListView() { List<Map<String, Object>> data = new ArrayList<Map<String, Object>>(); int size = itemlist.size(); for (int i = 0; i < size; ++i) { HashMap<String, Object> item = new HashMap<String, Object>(); item.put(RSSItem.TITLE, itemlist.get(i).getTitle()); item.put(RSSItem.PUBDATE, itemlist.get(i).getPubdate()); data.add(item); } return data; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPubdate() { return pubdate; } public void setPubdate(String pubdate) { this.pubdate = pubdate; } }
3、第三步是最重要的一步,即定义一个Handler,继承DefaultHandler:
public class RSSHandler extends DefaultHandler { RSSView _RSSView; RSSItem _RSSItem; String lastElementName = ""; final int RSS_TITLE = 1; final int RSS_LINK = 2; final int RSS_DESCRIPTION = 3; final int RSS_CATEGORY = 4; final int RSS_PUBDATE = 5; int currentstate = 0; public RSSHandler() { } public RSSView getRSSListView() { return _RSSView; } @Override public void characters(char[] ch, int start, int length) throws SAXException { String theString = new String(ch, start, length); switch (currentstate) { case RSS_TITLE: _RSSItem.setTitle(theString); currentstate = 0; break; case RSS_LINK: _RSSItem.setLink(theString); currentstate = 0; break; case RSS_DESCRIPTION: _RSSItem.setDescription(theString); currentstate = 0; break; case RSS_CATEGORY: _RSSItem.setCategory(theString); currentstate = 0; break; case RSS_PUBDATE: _RSSItem.setPubdate(theString); currentstate = 0; break; default: return; } // super.characters(ch, start, length); } @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub // super.endDocument(); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (localName.equals("item")) { _RSSView.addItem(_RSSItem); return; } // super.endElement(uri, localName, qName); } @Override public void startDocument() throws SAXException { _RSSView = new RSSView(); _RSSItem = new RSSItem(); // super.startDocument(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // TODO Auto-generated method stub if (localName.equals("item")) { _RSSItem = new RSSItem(); return; } if (localName.equals("channel")) { currentstate = 0; return; } if (localName.equals("title")) { currentstate = RSS_TITLE; return; } if (localName.equals("description")) { currentstate = RSS_DESCRIPTION; return; } if (localName.equals("link")) { currentstate = RSS_LINK; return; } if (localName.equals("category")) { currentstate = RSS_CATEGORY; return; } if (localName.equals("pubDate")) { currentstate = RSS_PUBDATE; return; } currentstate = 0; // super.startElement(uri, localName, qName, attributes); } } 4、在ShowRSSItems.java中用SAX API来操作: public class ShowRSSItems extends Activity implements OnItemClickListener { private RSSView rssview = null; String RSS_TITLE = ""; String RSS_URL = ""; String RID = ""; TextView tv; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show_rss_item); tv = (TextView) this.findViewById(R.id.rsstextview_); // 根据选择的站点加载数据 // RSS_URL = this.getIntent().getExtras().getString("A_RSS_INFO"); Bundle bundle = this.getIntent().getBundleExtra("A_RSS_INFO"); if (bundle != null) { RSS_TITLE = bundle.getString(RSSMainActivity.RSS_T_L[0]); RSS_URL = bundle.getString(RSSMainActivity.RSS_T_L[1]); RID = bundle.getString(RSSID); // this.setTitle(RSS_TITLE + "(ID:" + RID + ")"); this.setTitle(RSS_TITLE); } else { tv.setText("不好意思,程序出错啦!"); return; } rssview = getRssView(RSS_URL); showListView(); } private RSSView getRssView(String urlString) { try { URL url = new URL(urlString); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader xmlreader = parser.getXMLReader(); RSSHandler rssHandler = new RSSHandler(); xmlreader.setContentHandler(rssHandler); InputSource inputsource = new InputSource(url.openStream()); xmlreader.parse(inputsource); return rssHandler.getRSSListView(); } catch (Exception ee) { tv.setText(RSS_URL + "/n" + ee.toString()); return null; } } private void showListView() { ListView itemlist = (ListView) findViewById(R.id.rssItemView); if (rssview == null) { setTitle("访问RSS无效!"); return; } SimpleAdapter adapter = new SimpleAdapter(this, rssview .getAllItemForListView(), android.R.layout.simple_list_item_2, new String[] { RSSItem.TITLE, RSSItem.PUBDATE }, new int[] { android.R.id.text1, android.R.id.text2 }); itemlist.setAdapter(adapter); itemlist.setOnItemClickListener(this); itemlist.setSelection(0); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent itemintent = new Intent(this, ShowDescription.class); Bundle b = new Bundle(); b.putString("title", rssview.getItem(position).getTitle()); b.putString("description", rssview.getItem(position).getDescription()); b.putString("pubdate", rssview.getItem(position).getPubdate()); b.putString("link", rssview.getItem(position).getLink()); itemintent.putExtra("Android.intent.extra.RSSItem", b); this.startActivityForResult(itemintent, 0); } }
相关文章推荐
- PHP生成RSS文件类实例
- Vue 2.0 起步(2) 组件及 vue-router实例 - 微信公众号RSS
- iphone Dev 开发实例8: Parsing an RSS Feed Using NSXMLParser
- Android RSS客户端开发实例之一:RSS概述
- Vue 2.0 起步 (3) 数据流 vuex 和 LocalStorage 实例 - 微信公众号 RSS
- PHP读取RSS(Feed)简单实例
- 简单的Rss实例代码
- Android RSS客户端开发实例之二:如何解析XML文件
- java使用Rome解析Rss的实例(转)
- PHP 实例 - AJAX RSS 阅读器
- Android RSS客户端开发实例之三:在UI中显示RSS列表
- Flask MVVM 开发(vue.js) 实例 -- 微信公从号RSS
- Vue 2.0 起步(2) 组件及 vue-router实例 - 微信公众号RSS
- rss 开发实例 1 AbstractFeedServlet
- 实例1:使用GOOGLE提供的JS和CSS来显示RSS内容
- Vue 2.0 起步 (3) 数据流 vuex 和 LocalStorage 实例 - 微信公众号 RSS
- rss 开发实例2 getFeed()方法得实现
- 实例2:查找符合查询条件的RSS
- PHP读取RSS(Feed)简单实例
- java使用Rome解析Rss的实例