上面咱們已經把頁面弄好了,下面咱們就要在裏面實現咱們的功能了哦,今天主要是在RemoteMp3Activity中作功夫,由於項目啓動後,這個Activity要作不少事情哦:html
1)從服務器上面下載mp3.xml文件,將其轉化爲string格式;java
2)解析xml文件,這裏使用的是SAX解析技術,若是你們對XML和XML解析這部分不清楚的話,仍是老話,本身從網上查找相關的信息去學習一下,鍛鍊本身的自學能力;將解析出來的mp3信息轉換爲MP3對象,並保存在List集合中;android
3)在ListActivity中顯示出來;數組
好了,咱們分爲上面四步,那就咱們一步一步來吧!!服務器
1、從服務器上面下載mp3.xml文件,將其轉化爲string格式,咱們新建兩個類,一個類專門用來下載:HttpDownloader,一個類用來操做文件的輔助類,例如獲得SD卡的路徑,建立文件,判斷文件是否存在等等,取名爲FileUtils,先來開發咱們的HttpDownloader吧:app
public class HttpDownloader { private URL url=null; //下載文件,該文件主要是文本類型文件,返回其中的內容 public String download(String urlStr){ StringBuffer sb=new StringBuffer(); String line=null; BufferedReader buffer=null; try { //建立一個URL對象 url=new URL(urlStr); //建立一個Http鏈接 HttpURLConnection urlConn=(HttpURLConnection)url.openConnection(); //使用IO流讀取數據 buffer=new BufferedReader(new InputStreamReader(urlConn.getInputStream())); while((line=buffer.readLine())!=null){ sb.append(line); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { buffer.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } }
這個方法的做用是從服務器上下載文本文件,並將其轉換爲String類型的字符串,在裏面一個重要的點事android提供的HttpURLConnection類,它能夠經過Url地址直接得到鏈接,而後進行相應的文件操做便可,經過傳入的地址參數,我這裏使用的地址是:http://192.168.1.104:8080/video/mp3.xml,將地址傳入過去,就能夠從服務器上獲得咱們想要的xml文件中的內容信息了!ide
2)解析XML字符串信息,將信息轉化爲對象保存在List集合中函數
首先咱們須要建立Mp3對象信息,取名爲Mp3Info,並生成其相應的get和set方法,重寫toString方法主要是方便項目的調試:佈局
package com.harderxin.model; import java.io.Serializable; public class Mp3Info implements Serializable{ /** * */ private static final long serialVersionUID = 1637894703074747542L; private String id; private String mp3Name; private String mp3Size; private String lrcName; private String 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; } @Override public String toString() { return "Mp3Info [id=" + id + ", mp3Name=" + mp3Name + ", mp3Size=" + mp3Size + ", lrcName=" + lrcName + ", lrcSize=" + lrcSize + "]"; } }
其次,咱們須要建立XML內容解析器,由於是SAX解析,咱們這裏繼承的類是DefaultHandler(爲何這麼作,這就跟SAX解析相關的知識點有關係哦),而後重寫裏面的方法,代碼裏面有相應的註釋哦:學習
package com.harderxin.utils; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import com.harderxin.model.Mp3Info; /** * 運用了一種適配器模式,由於DefaultHandler實現了ContentHandler接口 * 可是ContentHandler須要實現的方法不少,因此定義一個DefaultHandler * 實現其中的方法,咱們只需繼承它覆寫咱們須要的方法便可 <resources> <resource> <id>1</id> <mp3.name>qmys.mp3</mp3.name> <mp3.size>3557358</mp3.size> <lrc.name>qmys.lrc</lrc.name> <lrc.size>1294</lrc.size> </resource> <resource> <id>2</id> <mp3.name>proud.mp3</mp3.name> <mp3.size>3047992</mp3.size> <lrc.name>proud.lrc</lrc.name> <lrc.size>2078</lrc.size> </resource> </resources> * @author Administrator * */ public class Mp3ListContentHandler extends DefaultHandler{ private String tagName; private Mp3Info mp3Info;//定義一個全局變量的標籤名稱 private List<Mp3Info> mp3Infos; //構造方法,將List集合傳入進去 public Mp3ListContentHandler(List<Mp3Info> mp3Infos) { super(); this.mp3Infos = mp3Infos; } //解析其中的文本<mp3.name>qmys.mp3</mp3.name>--->qmys.mp3 @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 { super.endDocument(); } //解析結束元素 @Override public void endElement(String uri, String localName, String qName) throws SAXException { if(localName.equals("resource")){ mp3Infos.add(mp3Info); } tagName=""; } //解析Document @Override public void startDocument() throws SAXException { //解析<resources>部分 super.startDocument(); } /** * 解析Element * namespaceURI 命名空間 * localName 不帶前綴部分<worker id="001">--->worker * qName 帶前綴部分<abc:worker id="001">---->abc:worker * attributes 屬性集合 <abc:worker id="001">---->id="001".... */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //解析<resource>部分 tagName=localName; if(tagName.equals("resource")){ mp3Info=new Mp3Info(); } } }
上面解析後的xml文件將會轉換爲Mp3Info對象,最後保存在List集合中!
3)在ListActivity中顯示:
在RemoteMp3Activity中,咱們根據方法傳入相應的參數便可,由於程序中講究功能單一性,減小耦合,因此我把各部分的功能就用一個個方法在RemoteMp3Activity中寫出來:
根據地址從服務器獲取XML文件,將其轉內容換爲String類型:
/** * 從服務器上面獲取XML文件信息,並將其中信息轉換爲字符串 * @param url * @return */ private String downLoadXML(String url){ HttpDownloader httpDownloader=new HttpDownloader(); String xmlStr=httpDownloader.download(url); return xmlStr; }
根據字符串解析出Mp3信息,將其轉換爲Mp3對象保存在List集合中:
/** * 解析XML文件,並將mp3Info信息放入到List集合中 * @param xmlStr * @return */ private List<Mp3Info> parseXML(String xmlStr){ List<Mp3Info> mp3Infos=new ArrayList<Mp3Info>(); SAXParserFactory saxFactory=SAXParserFactory.newInstance(); try { XMLReader xmlReader=saxFactory.newSAXParser().getXMLReader(); xmlReader.setContentHandler(new Mp3ListContentHandler(mp3Infos)); xmlReader.parse(new InputSource(new StringReader(xmlStr))); }catch(Exception e){ e.printStackTrace(); } return mp3Infos; }
創建SimpleAdapter對象,這裏須要跟你們說明一下,由於咱們繼承了ListActivity,其中的控件顯示方式如咱們之前看到的那種,就是一列一列的,它是經過咱們的代碼去控制的,須要創建一個SimpleAdapter對象,裏面須要幾個參數,你們還記得咱們在創建佈局文件的時候,創建過一個mp3_item.xml文件嗎,由於這裏就須要用到它,它是其中的一個參數,另外咱們還須要一個List<HashMap<String,String>>這樣一個對象,咱們得經過List<Mp3Info>去轉換,其中的HashMap<String,String>裏面的鍵值要和mp3_item.xml中的id值要同樣,至於爲何,那就要問android系統了,由於它裏面就是這樣規定的,咱們得按照它的要求來,若是你們仍是不懂的話,那就看一下android控件章節,ListActivity的案列吧,應該就明白了,我下面的代碼裏面也有註釋哦!
/** * 創建SimpleAdapter對象 * @param mp3Infos * @return */ private SimpleAdapter buildSimpleAdapter(List<Mp3Info> mp3Infos){ List<HashMap<String,String>> list=new ArrayList<HashMap<String,String>>(); HashMap<String,String> map=null; //將List<Mp3Info>轉換爲List<HashMap<String,String>>對象 //HashMap裏面的鍵值要和咱們的mp3_item.xml中的id同樣 for(Mp3Info mp3Info:mp3Infos){ map=new HashMap<String,String>(); map.put("mp3_name", mp3Info.getMp3Name()); map.put("mp3_size", mp3Info.getMp3Size()); list.add(map); } //注意參數要一致,HashMap裏面的鍵值、參數中String數組、mp3_item.xml中的id要同樣 SimpleAdapter simpleAdapter=new SimpleAdapter(RemoteMp3Activity.this, list, R.layout.mp3info_item, new String[]{"mp3_name","mp3_size"}, new int[]{R.id.mp3_name,R.id.mp3_size}); return simpleAdapter; }
好了,上面三個函數都封裝好了,那就開始寫咱們的顯示頁面這個方法吧,就是一步一步去調用上面的幾個方法啦!
/** * 軟件中講究功能單一性,以方便代碼的重用,減小冗餘代碼 */ private void updateListView(){ String xmlStr=downLoadXML("http://192.168.1.104:8080/mp3/mp3.xml"); mp3Infos=parseXML(xmlStr); SimpleAdapter simpleAdapter=buildSimpleAdapter(mp3Infos); setListAdapter(simpleAdapter); }
相信你們很容易弄懂,這樣寫就是方便調用,若是還有其餘地方須要這些重複的代碼,咱們只須要調用方法一次就能夠咯,減小代碼冗餘!
好了,接下來在咱們昨天寫的onCreate方法中調用顯示頁面這個方法吧!
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.remote_mp3_list); updateListView(); }
這樣寫,是否是你們以爲代碼可複用性很高呢,之後寫代碼的時候要養成這樣的好習慣哦,不要在一個方法中寫處理太多邏輯的代碼,到時候可能形成同樣的功能咱們要寫不少重複的代碼,這是一個很很差的習慣,對之後程序的維護會形成不少很差的影響哦,因此你們得注意一下!!
最後還有一個事要作哦,就是咱們訪問服務器的時候,須要一個權限,另外,咱們訪問SD卡的時候也須要一個權限,否則android系統可不會讓你去直接操做哦,這個權限須要在AndroidMainifest.xml中進行配置,加上下面幾行代碼吧:
<!-- 得到相應的權限 --> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
上面分別表示得到外部訪問權限和SD卡的可讀訪問權限,必定要加上,否則會報錯!!
好了,代碼寫到這裏,咱們這部分功能就算完工咯,運行一下這個項目吧,保證咱們的Tomcat服務器是啓動的哦,咱們就能夠在模擬器上看到服務器上面的MP3文件的信息咯,我這裏顯示的是MP3文件的名稱和大小:
你們在實踐的過程當中,若是有什麼問題,或者你們有什麼意見,能夠給本博客留言哦,你們一塊兒交流分享,共同窗習,下一講我將會實現:點擊一個MP3文件,從服務器上找到相應的文件,下載到SD卡中,而後在LocalMp3Activity中顯示出來!!