仿Mars MP3播放器项目3

  1.在src中新建一个包*.xml,在其中新建一个类Mp3ListContentHandler继承DefaultHandler,以便设置SAX解析的时的Handler,直接附上代码先:

  

public class Mp3ListContentHandler extends DefaultHandler{
	private List<Mp3Info> infos = null;
	private Mp3Info mp3Info = null;
	private String tagName = null;
	
	public Mp3ListContentHandler(List<Mp3Info> infos) {
		super();
		this.infos = infos;
	}
	
	public List<Mp3Info> getInfos() {
		return infos;
	}

	public void setInfos(List<Mp3Info> infos) {
		this.infos = infos;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		String temp = new String(ch,start,length);
		if(tagName.equals("id")){
			mp3Info.setId(temp);
		}
		else if(tagName.equals("mp3.name")){
			mp3Info.setMp3Name(temp);
		}
		else if(tagName.equals("mp3.size")){
			mp3Info.setMp3Size(temp);
		}
		else if(tagName.equals("lrc.name")){
			mp3Info.setLrcName(temp);
		}
		else if(tagName.equals("lrc.size")){
			mp3Info.setLrcSize(temp);
		}
	}
	
	@Override
	public void endDocument() throws SAXException {

	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if(qName.equals("resource")){
			infos.add(mp3Info);
		}
		tagName = "";
	}
	

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		this.tagName = localName;
		if(tagName.equals("resource")){
			mp3Info = new Mp3Info();
		}
	}
  	

     a.每解析到<resource>的startElement时,表示一个新的MP3对象被解析到,创建新的mp3Info对象存储Mp3对象

    b.每解析到</resource>的endElement时,表示一个MP3对象的解析完成,将这个mp3Info对象放到infos中

  2. c.这里需要用到Mp3Info对象,因此创建一个Mp3Info类,用来实现在XML文件解析过程中对每个MP3的属性进行存储,我们放在/src/*.model/中,代码如下:

      

public class Mp3Info implements Serializable {
	private String id;
	private String mp3Name;
	private String mp3Size;
	private String lrcName;
	private String lrcSize;
	
	public Mp3Info(String id, String mp3Name, String mp3Size, String lrcName,
			String lrcSize) {
		super();
		this.id = id;
		this.mp3Name = mp3Name;
		this.mp3Size = mp3Size;
		this.lrcName = lrcName;
		this.lrcSize = lrcSize;
	}
	
	public Mp3Info() {
		super();
	}
	
	@Override
	public String toString() {
		return "Mp3Info [id=" + id + ", mp3Name=" + mp3Name + ", mp3Size="
				+ mp3Size + ", lrcName=" + lrcName + ", lrcSize=" + lrcSize
				+ "]";
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getMp3Name() {
		return mp3Name;
	}
	public void setMp3Name(String mp3Name) {
		this.mp3Name = mp3Name;
	}
	public String getMp3Size() {
		return mp3Size;
	}
	public void setMp3Size(String mp3Size) {
		this.mp3Size = mp3Size;
	}
	public String getLrcName() {
		return lrcName;
	}
	public void setLrcName(String lrcName) {
		this.lrcName = lrcName;
	}
	public String getLrcSize() {
		return lrcSize;
	}
	public void setLrcSize(String lrcSize) {
		this.lrcSize = lrcSize;
	}

   

  a.在编程中,对于这种专门用于存储某种实体对象的属性的类,都可以用上面的方法进行处理:

    1.将每个属性定义为一个私有变量

    2.自动生成get函数,set函数和构造函数的功能

    3.自动生成toString函数

  b.这里Mp3Info类定义了一个Serializable接口,使用序列化,为了保存内存中的实例变量并且可以把保存的实例变量给读取出来,具体的内容可以参考《附》

  

 3. Mp3ListActivity中通过SAX解析resources.xml中的信息,代码如下:

    

	private List<Mp3Info> parse(String xmlStr){
		SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
		List<Mp3Info> infos = new ArrayList<Mp3Info>();
		try{
			XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();
			Mp3ListContentHandler mp3ListContentHandler = new Mp3ListContentHandler(infos);
			xmlReader.setContentHandler(mp3ListContentHandler);
			xmlReader.parse(new InputSource(new StringReader(xmlStr)));
			for(Iterator iterator = infos.iterator();iterator.hasNext();){
				Mp3Info mp3Info = (Mp3Info)iterator.next();
				System.out.println(mp3Info);
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return infos;
	}

   a.新建一个SAXParserFactory的工厂类

   b.通过该工厂类产生一个SAX的解析类SAXParser

   c.从SAXParser中得到一个XMLReader实例

   d.将mp3ListContentHandler注册到XMLReader中

   e.将xml资源变成一个JAVA可处理的InputStream留,解析开始

 

  4.通过ListView将服务器上的xml内容显示出来

    这里我要用到List<HashMap<String ,String>>以及 SimpleAdapter。先上代码:

  

	private void updateListView() {
		//下载包含所有MP3基本信息的xml文件
		String xml = downloadXML("http://10.0.2.2:8080/mp3/resources.xml");
		//对xml进行解析,并将解析结果放置在mp3Info对象当中,最后将mp3Info对象放置到list当中
		mp3Infos = parse(xml);
		//生成list对象,按照SimpleAdapter标准,将mp3Info当中的数据添加到list当中
		List<HashMap<String ,String>> list = new ArrayList<HashMap<String,String>>();
		for(Iterator iterator = mp3Infos.iterator();iterator.hasNext();){
			Mp3Info mp3Info = (Mp3Info)iterator.next();
			HashMap<String,String> map = new HashMap<String,String>();
			map.put("mp3_name", mp3Info.getMp3Name());
			map.put("mp3_size", mp3Info.getMp3Size());
			list.add(map);
		}
		//创建一个SimpleAdapter对象
		SimpleAdapter simpleAdapter = new SimpleAdapter(this, 
								 list,
								 R.layout.mp3info_item,
new String[]{"mp3_name","mp3_size"}, new int[]{R.id.mp3_name,R.id.mp3_size}); //将SimpleAdapter对象设置到ListActivity当中 setListAdapter(simpleAdapter); }

    a.通过迭代并且设置value和对应的key值,将其存放在SimpleAdapter中,然后再set到list中,这样可以显示出ListView中的内容

 

  5.Menu

  点击Menu按键出现选项菜单,其内容有更新列表和退出。需要用到的2个函数为:onCreateOptionsMenu和onOptionsItemSelected,代码如下:

  

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		menu.add(0,UPDATE,1,R.string.mp3list_update);
		menu.add(0,ABOUT,2,R.string.mp3list_about);
		return super.onCreateOptionsMenu(menu);
		
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		if(item.getItemId() == UPDATE){
			updateListView();
		}
		else if(item.getItemId() == ABOUT){
			
		}
		
		return super.onOptionsItemSelected(item);
	}

  a.onCreateOptionsMenu(Menu menu),此方法用于初始化菜单,其中的menu参数就是要即将显示的Menu实例,返回为true则显示menu,返回false则不显示,只在第一次初始化    菜单调用

  b.onOptionsItemSelected(MenuItem item),此方法是菜单项监听,每次菜单项被点击,则要调用一次onOptionsItemSelected(MenuItem item)方法,item参数即为被点击的菜    单项,因此需要在此方法中判断是哪个菜单项被点击,并且根据点击的不同菜单项响应不同的事件

  c.menu.add (int groupId, int itemId, int order, int titleRes)

    groupId:组别

    itemId:Unique item ID,Android根据这个Id来确定不同的菜单 

    order:顺序

    titleRes:Resource identifier of title string

    

  下次将介绍本地local的界面的代码,留意~谢谢!

   

附: SAX解析的相关资料:

  http://www.iteye.com/topic/763895

   http://www.cnblogs.com/felix-hua/archive/2012/01/10/2317404.html

  http://blog.163.com/liyinhui20080527@126/blog/static/815232582012114115014900/

 

  序列化的相关资料:

  http://developer.51cto.com/art/200908/147650.htm

  http://xiebh.iteye.com/blog/121311

  

  ListView的相关资料:

  http://www.cnblogs.com/allin/archive/2010/05/11/1732200.html

  http://blog.csdn.net/hellogv/article/details/4542668

 

  menu的相关资料:

  http://android.yaohuiji.com/archives/636

  http://www.cnblogs.com/giuz/archive/2010/10/19/1855235.html

  http://www.cnblogs.com/salam/archive/2011/04/04/2005329.html

  

posted @ 2013-07-26 10:29  RoseAndroid  阅读(220)  评论(0编辑  收藏  举报