最近學校組織做實訓,分到的任務是做Android的天氣預報軟件,我分到的任務是制作生活小貼士的部分。主要是關於空氣質量、洗車指數一類的信息的顯示,我使用的API是新浪天氣的API,新浪天氣的API提供的主要是XML文件。
新浪天氣API的介紹我主要是參考http://www.linuxidc.com/Linux/2014-03/97743.htm,這個博客講解的很細致,網絡上關於新浪天氣大多都跟這個博客的類似。
API接口如下:
http://php.weather.sina.com.cn/xml.php?city=%B1%B1%BE%A9&password=DJOYnieT8234jlsK&day=0
其中,city後的城市轉碼。
Password固定
Day為0表示當天天氣,1表示第二天的天氣,2表示第三天的天氣,以此類推,最大為4。
city後的城市轉碼這句很籠統,為難了我一陣,在這裡分享一下,這個轉碼需要使用GB2312來轉換,就是類似
String city = java.net.URLEncoder.encode("北京","gb2312");
這樣就可以直接轉為我們需要的城市的轉碼。
接下來是關於解析XML文件,我使用的是XmlPullParser的方法解析。
1. 實例化一個XML解析器XmlPullParser
2. 給實例化的XML解析器所需要的xml資源
如:XmlPullParser parser = Xml.newPullParser();
parser.setInput(is, "UTF-8");
(is是從網絡上獲取的InputStream的字符流)
以上,XML解析器就獲取了需要解析的XML文件。
接下來就是要解析獲取的XML數據。
1. 得到XML標簽
2. 通過循環語句對標簽進行遍歷獲取想要的數據
例如:XML文件示例如下:
<Students>
<Student>
<id>1001</id>
<name>zhangsan</name>
</Student>
<Student>
<id>1002</id>
<name>lisi</name>
</Student>
</Students>
上面的解析器得到xml數據之後,解析的過程如下:
int type = parser.getEventType(); // 得到xml數據的標簽
// 循環語句進行遍歷
while(type != parser.END_DOCUMENT) // 在xml的標簽不為結束標簽時進行遍歷,就是上面的</Students>標簽
{
switch(type){// 判斷標簽類型,這個標簽的數值我們可以從Android導入的包中查詢到,以下提供一些常用的
// START_DOCUMENT:0END_DOCUMENT:1 START_TAG:2END_TAG:3 TEXT:4
case XmlPullParser.START_DOCUMENT: // START_DOCUMENT指一個實例的的開始標簽,即<Student>
// 你的代碼
break;
case XmlPullParser.START_TAG:// START_TAG指一個標簽的開始,即<id>和<name>
// 一般在這個case中獲取數據, 例如:
String name = parser.getName();// 獲取標簽標題
if(name.equals("id"))
{
System.out.println(parser.nextText());// parser.nextText()這個語句表示獲取標簽中的內容
}
if(name.equals("name"))
{
System.out.println(parser.nextText());
}
break;
case XmlPullParser.END_TAG:// END_TAG指一個標簽的結束,即</id>和</name>
break;
}
parser.next();// 解析器移向下一個標簽
type = parser.getEventType();// 獲取標簽類型
}
這樣一個xml就解析結束了。
以下是我今天出現的BUG以及調試的結果,與君共勉。
BUG1:我在每一個case裡向兩個數據包裡傳遞了數據,都是使用的parser.nextText()語句進行獲取數據並傳遞。
只有第一個數據包接收到了第一個數據,其他數據都沒有顯示。
這個BUG我調試了一個下午才發現問題,所以一定要記錄下來。
問題就在於parser.nextText()不能連續對一個標簽使用兩次。在發現問題之後,我對XmlPullParser的理解是,這個類實例化之後是個類似於指針的東西,這個東西只能向下運動和讀取數據,因此我執行的第二次parser.nextText()操作使這個指針指向了一個未知的地方。
因此我們需要使用該數據時,可以先String temp = parser.nextText();然後可以多次調用temp這個變量。
BUG2:我們再解析數據的之後,很多時候是要把數據放入ListView控件中,但是很多時候他人為我們提供的XML文件的順序是亂的。
(當然JSON數據不會出現這種解析亂掉的問題,所以如果有JSON數據的接口還是比較建議使用JSON數據)
下面我舉個例子:例如我需要最近3天的天氣信息和溫度信息,而接口中提供的XML文件是3天的天氣信息放在前3行,3天的溫度信息放在後3行,當我們需要使用HashMap類的3個map實例來獲取信息並放入ArrayList時就無法像很多的例子中那樣直接使用循環,一個map裡應該放入一個天氣信息和一個溫度信息,但是一個在第1遍循環,一個在第4遍循環,會造成map放入list的混亂。
這種問題我提供一下我的解決方法,並不是最好的甚至有些麻煩,如果各位看官有更好的方法歡迎一同交流。
我的解決方法是,我建立了一個Data類,將所有我需要的數據放置進去,裡邊有get()和set()的函數,當其他人需要相關信息的時候,可以直接將這個實例化的變量傳遞出去。同時為了方便建立適配器,我還根據我的數據需要建立了一個二維的String數組,在解析的同時將數據同時放入數組中。
例如:String[][] weather = new String[3][2];final int DAY_ONE = 0; final int DAY_TWO = 1; final int DAY_THREE = 2; final int STATUS = 0; final int TEM = 2;
定義這些全局變量方便以將數據放入數組。這樣我們在建立ArrayList的時候就可以使用循環來創建map並將之放入ArrayList。
更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11