现在的位置: 首页 > 综合 > 正文

RSS新闻阅读器—相关android技术知识点

2018年06月10日 ⁄ 综合 ⁄ 共 8219字 ⁄ 字号 评论关闭

一、Handler消息处理器:android.os.Handler

用来发送和接收处理消息,一般用来处理子线程发来的消息。

当应用程序启动时,Android首先会开启一个主线程(也就是UI线程),主线程为管理界面中的UI控件,进行事件分发,比如说,你要是点击一个Button,Android会分发事件到Button上,来响应你的操作。  如果此时需要一个耗时的操作,例如:联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收到Android系统的一个错误提示  "强制关闭", 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的.这个时候,由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的Message对象(里面包含数据)  ,把这些消息放入主线程队列中,配合主线程进行更新UI

实现:
1、在主线程中创建:

mHandler = new Handler() 
{
   @Override
   public void handleMessage(Message msg)
  {//重载消息处理函数			
      super.handleMessage(msg);
     do();//在该函数中对消息处理
  }			
};

2、在子线程中发送消息:

mHandler.sendMessage(msg);

3、消息生成

Message msg = new Message();//创建一个新消息,需要new重新开辟空间

Message msg = mHandler.obtainMessage();//从消息处理器的消息池里取出一个,不需要new,效率高。

当然消息可以加参数,处理消息时也可以获取这些参数进行处理。

二、Thread子线程处理类:java.lang.Thread,这个属于java中的类,不是android的

1、创建线程:此时只是创建,线程还没有启动

Thread thread = new Thread(new Runnable()
{		
  public void run()
  {//线程运行函数
     do();//线程中进行相关处理
  }			
});	

其实,这个代码这样写就明白了

//先创建运行接口,在接口里指明运行函数
Runnable runnable = new Runnable()
{
  public void run()
	{//线程运行函数
		do();	//线程中进行相关处理
	}		
}
//以这个运行接口为参数创建线程,当线程启动时则运行接口里的run函数
Thread thread = new Thread(runnable);

2、启动线程:
thread.start(); 

三、在程序中创建菜单:android.view.Menu

android程序一般没有菜单栏,但是可以通过手机面板上的menu键实现菜单的功能。Android一共有三种形式的菜单: 1.选项菜单(optinosMenu) 2.上下文菜单(ContextMenu)    3.子菜单(subMenu)
其中最常用的就是选项菜单(optionsMenu), 该菜单在点击 menu 按键后会在对应的Activity底部显示出来。Activity有一套机制来实现对菜单的管理。

选项菜单实现:

1、public boolean onCreateOptionsMenu(Menu menu):此方法用于初始化菜单,其中menu参数就是即将要显示的Menu实例。返回true则显示该menu,false 则不显示;
 
(只会在第一次初始化菜单时调用,系统提供此运行时自动调用的函数,方便创建菜单)

   添加菜单项:menu.add((int groupId, int itemId, int order, charsequence title) .setIcon(drawable ID)

       add()方法的四个参数,依次是: 

      1、组别,如果不分组的话就写Menu.NONE, 

      2、Id,这个很重要,Android根据这个Id来确定不同的菜单 

      3、顺序,哪个菜单项在前面由这个参数的大小决定 

      4、文本,菜单项的显示文本

       add()方法返回的是MenuItem对象,调用其setIcon()方法,为相应MenuItem设置Icon
2、菜单响应函数:public boolean onOptionsItemSelected(MenuItem item)
               菜单项被点击时调用,也就是菜单项的监听方法。
             
3.public void onOptionsMenuClosed(Menu menu):每次菜单被关闭时调用.

菜单被关闭有三种情形,menu按钮被再次点击、back按钮被点击或者用户选择了某一个菜单项)

四、RSS源解析的实现

1、要解析的RSS源文件格式样例

<rss version="2.0">
	<channel>
		<title>
			<![CDATA[IT-新浪博客]]>
		</title>
		<image>
			<title>
				<![CDATA[新浪博客频道]]>
			</title>
			<link>http://blog.sina.com.cn</link>
			<url>http://www.sinaimg.cn/blog/main/index2010/blog_logo.png</url>
		</image>
		<description>
			<![CDATA[IT博客列表]]>
		</description>
		<link>http://blog.sina.com.cn/lm/tech/</link>
		<language>zh-cn</language>
		<generator>WWW.SINA.COM.CN</generator>
		<ttl>5</ttl>
		<copyright>
			<![CDATA[Copyright 1996 - 2013 SINA Inc. All Rights Reserved]]>
		</copyright>
		<pubDate>Fri, 23 Aug 2013 07:39:40 GMT</pubDate>
		<category>
			<![CDATA[]]>
		</category>
		<item>
			<title>
				<![CDATA[百度轻应用想要做什么]]>
			</title>
			<link>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_88acd9c80101gld8.html</link>
			<author>WWW.SINA.COM.CN</author>
			<guid>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_88acd9c80101gld8.html</guid>
			<category>
				<![CDATA[IT博客]]>
			</category>
			<pubDate>Fri, 23 Aug 2013 06:35:27 GMT</pubDate>
			<comments></comments>
			<description>
				<![CDATA[]]>
			</description>
		</item>
		<item>
			<title>
				<![CDATA[互联网理财:值得借鉴的美国平台样板]]>
			</title>
			<link>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_bee732060101npb7.html</link>
			<author>WWW.SINA.COM.CN</author>
			<guid>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_bee732060101npb7.html</guid>
			<category>
				<![CDATA[IT博客]]>
			</category>
			<pubDate>Fri, 23 Aug 2013 06:05:08 GMT</pubDate>
			<comments></comments>
			<description>
				<![CDATA[]]>
			</description>
		</item>
		
	</channel>
</rss>

2、实现表示每个RSS条目的类

//Rssitem信息,用于存放RSS的每一个item
public class RssItem 
{
	public static final String TITLE = "title";
	public static final String PUBDATE = "pubDate";
	//标题
	private String title;
	//详细内容
	private String description;
	//链接
	private String link;
	//来源
	private String source;
	//日期
	private String pubDate;
	
	//获得标题
	public String getTitle() {
		return title;
	}
	//设置 标题
	public void setTitle(String title) {
		this.title = title;
	}
	//取得详细信息
	public String getDescription() {
		return description;
	}
	//设置详细信息
	public void setDescription(String description) {
		this.description = description;
	}
	//取得链接
	public String getLink() {
		return link;
	}
	//设置链接
	public void setLink(String link) {
		this.link = link;
	}
	//取得来源
	public String getSource() {
		return source;
	}
	//设置来源
	public void setSource(String source) {
		this.source = source;
	}
	//取得日期
	public String getPubDate() {
		return pubDate;
	}
	//设置日期
	public void setPubDate(String pubDate) {
		this.pubDate = pubDate;
	}
	
}

3、实现一个RSS源类

//RSS源类,用于存放一个RSS源的全部信息
public class RssFeed 
{
	//标题
	private String title;//RSS源、频道的标题
	//日期
	private String pubdate;//RSS源、频道的发布日期
	
	//条目数量
	private int itemcount;	
	
	//用于存放RSS信息的列表
	private List<RssItem> itemlist;	
	public RssFeed() 
	{
		itemlist = new Vector<RssItem>(0);
	}
	//添加元素
	public int addItem(RssItem item) {
		itemlist.add(item);
		itemcount++;
		return itemcount;
	}	
	//取得元素
	public RssItem getItem(int location) {
		return itemlist.get(location);
	}
	//取得所有列表需要的信息,存储到List
	public List getAllItemsForListView()
	{
		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;
	}
	//取得数量
	public int getItemcount() {
		return itemcount;
	}
	//设置数量
	public void setItemcount(int itemcount) {
		this.itemcount = itemcount;
	}
	//获得信息数组
	public List<RssItem> getItemlist() {
		return itemlist;
	}
	//设置信息数组
	public void setItemlist(List<RssItem> itemlist) {
		this.itemlist = itemlist;
	}	
}

4、创建一个RSS数据SAX解析时的处理器类

使用一系列工厂方法生成了一个XMLReader对象,随后,要通过reader.setContentHandler方法,为这个reader设置了一个处理器。使用SAX的时候,解析器会对XML文档进行深度优先遍历,在遍历的时候,会根据条件调用处理器中的方法。也就是说在解析的时候,可以调用我们自己的方法。

通过这个类可以在解析的时候,把RSS源的信息,充填到RssFeed类对象中。然后通过这个类的public RssFeed getFeed()这个方法获取已经充填数据的RssFeed类对象。

//RSS数据SAX解析
public class RssHandler extends DefaultHandler 
{
	RssFeed rssFeed;
	RssItem rssItem;
	private static boolean a = false;
	String lastElementName = "";
	final int RSS_TITLE = 1;
	final int RSS_LINK = 2;
	final int RSS_DESCRIPTION = 3;
	final int RSS_PUBDATE = 5;
	int currentstate = 0;
	
	public RssHandler() {
		
	}
	//返回rssFeed形式的信息
	public RssFeed getFeed() {
		return rssFeed;
	}
	//开始解析文档
	public void startDocument()throws SAXException {
		System.out.println("startDocument");
		//实例化RssFeed类和RssItem类
		rssFeed = new RssFeed();
		rssItem = new RssItem();
	}
	//文档结束
	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
	}
	//开始解析标签
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException 
	{
		super.startElement(uri, localName, qName, attributes);
		//channel标签
		if(localName.equals("channel")) {
			currentstate = 0;
			return;
		}
		//item标签
		if(localName.equals("item")) {
			rssItem = new RssItem();
			return;
		}
		//title标签
		if(localName.equals("title")) {
			currentstate = RSS_TITLE;
			return;
		}
		//详细信息标签
		if(localName.equals("description")) {	
				//跳过第一次遇到的description标签
			if(a == true) {
				currentstate = RSS_DESCRIPTION;
				return;
			} else {
				a = true;
				return;
			}
		}
		//链接
		if(localName.equals("link")) {
			currentstate = RSS_LINK;
			return;
		}
		//日期
		if(localName.equals("pubDate")) {
			currentstate = RSS_PUBDATE;
			return;
		}
		currentstate = 0;
	}
	//标签结束
	@Override
	public void endElement(String uri, String localName, String qName)	
			throws SAXException {
		//将信息添加到rssFeed中
		if(localName.equals("item")) {
			rssFeed.addItem(rssItem);
			return;
		}
	}
	//解析标签间的文本
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if(length <= 5) return ;
		String theString = new String(ch, start, length);
		switch (currentstate) {
		//标题
		case RSS_TITLE:
			rssItem.setTitle(theString);
			Log.e("title",theString);
			currentstate = 0;
			break;
			//链接
		case RSS_LINK:
			rssItem.setLink(theString);
			currentstate = 0;
			break;
			//详细信息
		case RSS_DESCRIPTION:
			System.out.println("RSS_DESCRIPTION=" + theString);		
			if(a == true) {
				rssItem.setDescription(theString);
				currentstate = 0;
			}else {			
				a = true;
			}
			break;
			//日期
		case RSS_PUBDATE:
			rssItem.setPubDate(theString);
			currentstate = 0;
			break;
		default:
			return;
		}
	}
}

5、实现解析

//根据URL实现解析
URL url = new URL(urlString);
//实例化SAX解析工厂类
SAXParserFactory factory = SAXParserFactory.newInstance();
//根据类工程创建SAX解析器
SAXParser parser = factory.newSAXParser();
//从SAX解析器获取XML阅读器
XMLReader xmlReader = parser.getXMLReader();
    		
//挂接事件处理对象到xmlReader上
RssHandler rssHandler = new RssHandler();  		
xmlReader.setContentHandler(rssHandler);
    		
//取得url网址内容,构造函数参数是字节流,它通过url.openStream()获取
InputSource is = new InputSource(url.openStream());
    		
//解析url网址内容
xmlReader.parse(is); 	
//返回RSS信息
RssFeed rssfeed = rssHandler.getFeed();

 

抱歉!评论已关闭.