基於Http協議的Android網路程式設計
寫在前面的話:好一陣子沒寫部落格了,心裡有點慚愧。在這期間我主要做了兩件事:一、之前在研究Android的過程中比較吃力,主要是Java的一些基礎知識掌握得還不太好,於是近半個月惡補了一下Java基礎,我發現自己連多型!多型!多型!(重要的事說三遍)這個面向物件的核心知識點都沒掌握,說起來真是太慚愧了,我都不知道自己在不懂多型這個知識點的情況下,是怎麼把Android的核心知識學下來的,要知道在Java以及Android的API中到處都是多型,現在打死我也能把多型發生的必要條件說出來了:1、要有類的繼承(或介面的實現);2、要有方法的重寫;3、要有父類引用指向子類物件。除了多型,托馬士兵老師的福(學了馬士兵Java視訊教程),我把Java程式碼在堆疊中的執行機制學了下,較好的理解了Java程式碼的記憶體執行機制,理解了這些再看Android程式碼,感覺比以前輕鬆多了!套用馬士兵老師的一句話,就是“掌握了Java程式碼在記憶體中的執行機制,就掌握了一切!” 二、除了夯實Java基礎,我還把郭霖前輩(《第一行程式碼》的作者)的部落格仔細研究了一下,不得不說郭大神除了程式碼寫的好,文筆也很棒,當初選擇《第一行程式碼》作為Android學習的入門書籍,絕對是正確決定。在部落格中,郭神通過原始碼的解讀,詳細剖析了Android中初學者不容易掌握的知識點,對於我這種菜鳥,絕對值得反覆研究,當然了,目前涉及到Android原始碼的內容,我還暫時無法理解,不過以後我會慢慢把它搞明白!:)
之前寫過一篇Android網路程式設計《淺談android網路程式設計》,隨著瞭解了更多Android知識,我意識到HttpClient已經不推薦使用了,更是在Android 6.0中被廢棄了,原因之一就是比起HttpURLConnection,HttpClient的封裝性更好,導致其可擴充套件性較差,當然現在網路程式設計更多的是使用框架了,HttpURLConnection被封裝了,socket也被封裝了,而像OKHttp和Volley這種框架,使用起來極為方便,開發者甚至不需要知道http、TCP/IP協議的相關知識就能高效地進行網路通訊,但在有些時候,當開發者遇到bug或是修改些涉及到基於原理的功能時,可能會因為沒能理解這些框架的原理而無法實現,所以本文就通過案例,著重分析基於Http協議的Android網路的原理實現,而不使用框架實現,當然更多的還是基礎知識。
基於Http協議的Android程式設計知識點概要
Android平臺網路相關API介面
- java.net.*(標準Java介面)
java.net.*提供與聯網有關的類,包括流、資料包套接字(socket)、Internet協議、常見Http處理等。比如:建立URL,以及URLConnection/HttpURLConnection物件、設定連結引數、連結到伺服器、向伺服器寫資料、從伺服器讀取資料等通訊。這些在Java網路程式設計中均有涉及。 - Org.apache介面
對於大部分應用程式而言JDK本身提供的網路功能已遠遠不夠,這時就需要Android提供的Apache HttpClient了。它是一個開源專案,功能更加完善,為客戶端的Http程式設計提供高效、最新、功能豐富的工具包支援。 - Android.net.*(Android網路介面)
常常使用此包下的類進行Android特有的網路程式設計,如:訪問WiFi,訪問Android聯網資訊,郵件等功能。
網路架構主要有兩種模式B/S,C/S
- B/S:瀏覽器/伺服器端模式,通過應用層的HTTP協議通訊,不需要特定客戶端軟體,而是需要統一規範的客戶端,簡而言之就是Android網路瀏覽器(如chrome,UcWeb,QQ瀏覽器等等)訪問web伺服器端的方式。
- C/S:客戶端/伺服器端模式,通過任意的網路協議通訊,需要特定的客戶端軟體。
伺服器端返回客戶端的內容有三種方式
- 以HTML程式碼的形式返回;
- 以XML字串的形式返回。通過XML解析(SAX、DOM,Pull 等);
- 以json物件的方式返回。
Http協議簡介
Http是Internet中廣泛使用的協議,幾乎所有的計算機語言和SDK都會不同程度地支援HTTP,而以網路著稱的Google公司自然也會使Android SDK擁有強大的HTTP訪問能力。在Android SDK中可以採用多種方式使用HTTP,例如HttpURLConnection、HttpClient ( HttpGet、HttpPost )等。
Http是一個屬於應用層的面向物件的協議,由於其簡捷、快速的方式,適用於分散式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴充套件。
Http協議的主要特點如下:
- 支援C/S模式;
- 簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶端與伺服器聯絡的型別不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
- 靈活:HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記。
- 無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
- 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。
HttpURLConnection類
HttpURLConnection類是jdk中的標準網路介面,該類的全限定名是java.net.HttpURLConnection,下面將介紹利用HttpURLConnection實現get請求和post請求。
HttpURLConnection實現GET請求
HttpURLConnection實現get請求步驟如下:
- 獲得需要訪問的server地址、方法、及引數鍵值;
- 建立URL物件,將上述訪問地址傳入;
- 呼叫URL.openConnection()方法返回HttpURLConnection物件;
- 呼叫HttpURLConnection.connect()方法連線server;
- 呼叫HttpURLConnection.respondCode()方法,根據返回碼判斷server返回是否正確;
- 呼叫HttpURLConnection.getInputStream()方法讀取server返回的內容;
- 關閉流、呼叫HttpURLConnection.disconnect()方法斷開連線。
示例如下:
首先在介面中新增一個按鈕,點選該按鈕,程式將嘗試請求上述server的相應資料並返回給程式,介面如下:
程式碼示例:
public class MainActivity extends AppCompatActivity {
private Button mButtonHttpUrlConnctionGet;
private String mUrl = "http://cloud.bmob.cn/0906a62b462a3082/";
private String mMethod = "getMemberBySex";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonHttpUrlConnctionGet = (Button) findViewById(R.id.button_httpurlconnection_get);
mButtonHttpUrlConnctionGet.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doGet("boy");
}
});
}
//doGet請求
private void doGet(String s) {
//1、獲得需要訪問的server地址、方法、及引數鍵值
final String serverAddress = mUrl + mMethod + "?" + "sex=" + s;
//訪問網路,開啟一個執行緒
new Thread(new Runnable() {
@Override
public void run() {
try {
//2、建立URL物件,將上述訪問地址傳入;
URL url = new URL(serverAddress);
//3、呼叫URL.openConnection()方法返回HttpURLConnection物件
HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
//4、呼叫HttpURLConnection.connect()方法連線server
httpUrlConnection.connect();
//5、呼叫HttpURLConnection.respondCode()方法,根據返回碼判斷server返回是否正確
if (httpUrlConnection.getResponseCode() == 200) {
//6、呼叫HttpURLConnection.getInputStream()方法讀取server返回的內容
InputStream is = httpUrlConnection.getInputStream();
//包裝流:位元組流->轉換字元流(處理流)->緩衝字元流(處理流)
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String readLine = "";
while ((readLine = br.readLine()) != null) {
sb.append(readLine);
}
//7、關閉流、呼叫HttpURLConnection.disconnect()方法斷開連線
is.close();
br.close();
httpUrlConnection.disconnect();
//Log日誌中顯示返回結果
Log.i("TAG", sb.toString());
} else {
Log.e("TAG", "failed to connect server!");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
LogCat顯示結果如下所示:
使用HttpURLConnection的get請求需要注意的地方:
- 需要在AndroidManifest中新增訪問網路的許可權:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
- 需要開啟子執行緒訪問網路
new Thread(new Runnable
{
//access the Internet
}).start();
HttpURLConnection實現POST請求
當需要向server寫資料時,就需要使用post請求。Http請求由三部分組成,分別是:請求頭、訊息報頭(可選)、請求正文。
Http響應也是由三個部分組成,分別是:響應頭、訊息報頭(可選)、響應正文。
其中請求頭允許客戶端傳遞關於自身的資訊和希望的響應形式,它負責通知伺服器有關客戶端請求的資訊,下表列出了http的請求頭,其中用黃色標記的請求頭較為常用:
與請求頭對應,響應頭域允許伺服器傳遞不能放在狀態行的附加資訊,下表列出了http的響應頭,其中用黃色標記的響應頭較為常用:
HttpURLConnection實現post請求步驟如下:
- 設定無引數的server訪問地址、方法;
- 建立URL物件,將上述訪問地址傳入;
- 呼叫URL.openConnection()方法返回HttpURLConnection物件;
- 呼叫HttpURLConnection.connect()方法連線server;
- 呼叫HttpURLConnection類中的setDoInput() [設定輸入流]、setDoOutput() [設定輸出流]、setRequestMethod() [設定請求型別]、setUseCaches() [設定是否使用快取]、setRequestProperty() [設定響應頭];
- 呼叫HttpURLConnection.getOutputStream()方法向server傳送資訊;
- 呼叫HttpURLConnection.connect()方法連線server;
- 呼叫HttpURLConnection.getInputStream()方法讀取server返回的內容;
- 關閉流、呼叫HttpURLConnection.disconnect()方法斷開連線。
由此看出,相比於get方式,post方式不允許將引數值出入URL物件,而是需要呼叫HttpURLConnection.getOutputStream()方法專門向server傳送引數資訊;另外,需要呼叫HttpURLConnection的方法設定輸入輸出流、響應頭等操作。
新增一個按鈕用於測試post請求:
下面是post請求的程式碼示例:
//doPost請求
private void doPost(final String s) {
//post請求的URL沒有請求引數
final String postAddress = mUrl + mMethod;
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(postAddress);
HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
//開啟HttpURLConnection的輸入輸出
httpUrlConnection.setDoInput(true);
httpUrlConnection.setDoOutput(true);
//設定請求為post請求
httpUrlConnection.setRequestMethod("POST");
//不使用快取
httpUrlConnection.setUseCaches(false);
//設定請求頭
//設定編碼集
httpUrlConnection.setRequestProperty("Accept-Charset", "UTF-8");
//設定content-type
httpUrlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//連線server
httpUrlConnection.connect();
//將需要傳送的引數資訊寫給server
OutputStream os = httpUrlConnection.getOutputStream();
//包裝流:資料輸出流(字元處理流)
DataOutputStream dos = new DataOutputStream(os);
String content = "sex" + s;
dos.writeBytes(content);
os.flush();
os.close();
dos.flush();
dos.close();
//獲得server返回資料
if (httpUrlConnection.getResponseCode() == 200) {
InputStream is = httpUrlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sb = new StringBuffer();
String readLine = "";
while ((readLine = br.readLine()) != null) {
sb.append(readLine);
}
is.close();
br.close();
httpUrlConnection.disconnect();
Log.i("POST_TAG", sb.toString());
} else {
Log.i("POST_TAG", "failed!");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
點選在LogCat中的顯示如下:
Get請求和Post請求的區別
上面介紹了使用HttpURLConnection類實現Get請求和Post請求,下面簡要介紹它們的區別:
- get是從伺服器上獲取資料,post是向伺服器傳送資料。
- get是把引數資料佇列tian新增到指定的URL中,引數值和引數名各個欄位一一對應,並且在URL中可以看到。post是通過HTTPpost機制,將請求的引數名和引數值放置在HTML HEADER內一起傳送到指定的URL地址。使用者看不到這個過程。
- 對於get方式,伺服器端用 Request.QueryString獲取變數的值,對於post方式,伺服器端用Request.Form獲取提交的資料。
- get 傳送的資料量較小,不能大於2KB。post傳送的資料量較大,一般被預設為不受限制。但理論上,IIS4中最大量為80KB,IIS5中為100KB。
- get安全性非常低,post安全性較高。
廢棄HttpClient類
在較低的Android API版本中,通過Org.apache.HttpClient,Android也能訪問網路,但在4.x及後續版本已不被推薦使用,更是在Android 6.0 (API 23)中被廢棄,很大一部分原因就是HttpClient類的封裝性很高,導致其擴充套件性不如HttpURLConnection。當然,如今HttpURLConnection類也被封裝的很好,OkHttp就是將其封裝得很好且擴充套件性更高的一個框架,下面將對OkHttp做簡單介紹。
使用OkHttp訪問網路
HttpURLConnection和HttpClient,雖然兩者都能滿足HTTPS流的上傳和下載,配置超時,IPv6和連線池等各種HTTP請求的需求,但更高效的使用HTTP可以讓我們的應用執行更快、更節省流量。而OkHttp庫就是為此而生。
OkHttp是一個高效的HTTP庫:
1、支援 SPDY ,共享同一個Socket來處理同一個伺服器的所有請求,如果SPDY不可用,則通過連線池來減少請求延時。
2、無縫的支援GZIP來減少資料流量
3、快取響應資料來減少重複的網路請求:會從很多常用的連線問題中自動恢復。如果伺服器配置了多個IP地址,當第一個IP連線失敗的時候,OkHttp會自動嘗試下一個IP。OkHttp還處理了代理伺服器問題和SSL握手失敗問題。
4、使用 OkHttp 無需重寫程式中的網路程式碼。OkHttp實現了幾乎和HttpURLConnection一樣的API。如果用了HttpClient,則OkHttp也提供了一個對應的okhttp-apache 模組。
5、OkHttp是一個相對成熟的解決方案,Android4.4的原始碼中已經將HttpURLConnection替換成了OkHttp。
使用OkHttp傳送GET請求
為了在程式中使用OkHttp框架,需要在gradle中新增依賴:
compile 'com.squareup.okhttp3:okhttp:3.2.0'
在佈局中新增兩個按鈕,用於傳送Get請求和Post請求。
以下是Get請求的程式碼示例:
private void doGet(String s) {
//拼接訪問server地址
final String address = new StringBuilder().append(mUrl).append(mMethod).append("?sex=").append(s).toString();
new Thread(new Runnable() {
@Override
public void run() {
//建立okhttp3.Request物件,傳入訪問地址
Request request = new Request.Builder().url(address).build();
try {
//使用同步方式獲得返回物件okhttp3.Response
Response response = mOkHttpCLient.newCall(request).execute();
//訪問成功
if (response.isSuccessful()) {
//呼叫Response.body().string()方法獲得server返回的結果
Log.i("TAG", response.body().string());
} else {
Log.i("TAG", "error!");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
使用OkHttp傳送POST請求
/**
* @param s post的請求引數
*/
private void doPost(String s) {
//建立FormBody物件,用於封裝post的請求引數
FormBody formBody = new FormBody.Builder().add("sex", s).build();
//建立Request物件,用於封裝URL請求地址及請求引數
Request request = new Request.Builder().url(new StringBuilder().append(mUrl).append(mMethod).toString()).post(formBody).build();
//採用非同步方式回撥server返回的結果
mOkHttpCLient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("TAG", "failed");
}
//該回調方法的返回引數Response就是server的返回結果
@Override
public void onResponse(Call call, Response response) throws IOException {
//輸出結果
Log.i("TAG", response.body().string());
}
});
}
有關OkHttp的更多學習資料,請您訪問:
解析JSON格式資料
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。它基於ECMAScript的一個子集。 JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網路傳輸速率)。
JSON資料的語法規則
JSON 語法規則:
1、資料在鍵值對中
2、資料由逗號分隔
3、花括號儲存物件
4、方括號儲存陣列
JSON 值可以是:
1、數字(整數或浮點數)
2、字串(在雙引號中)
3、邏輯值(true 或 false)
4、陣列(在方括號中)
5、物件(在花括號中)
6、null
JSON格式資料的優缺點
優點:
1、資料格式比較簡單,易於讀寫,格式都是壓縮的,佔用頻寬小;
2、易於解析,客戶端JavaScript可以簡單的通過eval()進行JSON資料的讀取;
3、支援多種語言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等伺服器端語言,便於伺服器端的解析;
4、在PHP世界,已經有PHP-JSON和JSON-PHP出現了,偏於PHP序列化後的程式直接呼叫,PHP伺服器端的物件、陣列等能直接生成JSON格式,便於客戶端的訪問提取;
5、因為JSON格式能直接為伺服器端程式碼使用,大大簡化了伺服器端和客戶端的程式碼開發量,且完成任務不變,並且易於維護。
缺點:
1、沒有XML格式這麼推廣的深入人心和喜用廣泛,沒有XML那麼通用性;
2、JSON格式目前在Web Service中推廣還屬於初級階段。
解析JSON資料
下面提供了一段JSON格式的資料:
下面程式碼將解析上述JSON資料:
/**
* @param json
*/
private void parseData(String json) {
JSONObject objectOutside = null;
try {
objectOutside = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
}
try {
String country = objectOutside.getString("name");
Log.i("TAG", "Country: " + country);
JSONArray provinces = objectOutside.getJSONArray("provinces");
for (int i = 0; i < provinces.length(); ++i) {
JSONObject objectInside = provinces.getJSONObject(i);
String province = objectInside.getString("name");
Log.i("TAG", "Province " + (i + 1) + ": " + province);
JSONObject objectCities = objectInside.getJSONObject("citys");
JSONArray arrayCity = objectCities.getJSONArray("city");
StringBuffer sb = new StringBuffer();
for (int j = 0; j < arrayCity.length(); ++j) {
String city = arrayCity.getString(j);
sb.append("City " + (j + 1) + ": " + city + " ");
}
Log.i("TAG", sb.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
解析結果如下所示:
解析XML格式資料
XML是一種可擴充套件標記語言:
1、可擴充套件標記語言是一種很像超文字標記語言的標記語言。
2、它的設計宗旨是傳輸資料,而不是顯示資料。
3、它的標籤沒有被預定義。您需要自行定義標籤。
4、它被設計為具有自我描述性。
5、它是W3C的推薦標準。
可擴充套件標記語言(XML)和超文字標記語言(HTML)之間的差異:
1、它不是超文字標記語言的替代。
2、它是對超文字標記語言的補充。
3、它和超文字標記語言為不同的目的而設計:
4、它被設計用來傳輸和儲存資料,其焦點是資料的內容。
5、超文字標記語言被設計用來顯示資料,其焦點是資料的外觀。
超文字標記語言(XML)存在的問題:
1、某些起始標籤可以選擇性出現結束標籤或者隱含了結束標籤。
2、標籤可以以任何順序巢狀,即使結束標籤不按照起始標籤的逆序出現也是允許的。
3、某些特性不要求一定有值。
4、定義特性的兩邊有沒有加上雙引號都是可以的,所以都是允許的。
可擴充套件標記語言如何解決問題:
1、任何的起始標籤都必須有一個結束標籤。
2、可以採用另一種簡化語法,可以在一個標籤中同時表示起始和結束標籤。
3、標籤必須按合適的順序進行巢狀,所以結束標籤必須按映象順序匹配起始標籤。
4、所有的特性都必須有值。
5、所有的特性都必須在值的周圍加上雙引號。
XML格式資料的優缺點
XML的優點:
1、格式統一,符合標準;
2、容易與其他系統進行遠端互動,資料共享比較方便。
XML的缺點:
1、XML檔案龐大,檔案格式複雜,傳輸佔頻寬;
2、伺服器端和客戶端都需要花費大量程式碼來解析XML,導致伺服器端和客戶端程式碼變得異常複雜且不易維護;
3、客戶端不同瀏覽器之間解析XML的方式不一致,需要重複編寫很多程式碼;
4、伺服器端和客戶端解析XML花費較多的資源和時間。
解析XML格式資料
下限是一段XML格式的資料:
<?xml version="1.0" encoding="gb2312"?>
<root>
<item>
<name>劉亦菲</name>
<url>MingXing/LiuYiFei.htm</url>
<color>red</color>
</item>
<item>
<name>蔡依林</name>
<url>MingXing/CaiYiLin.htm</url>
<color>blue</color>
</item>
<item>
<name>張娜拉</name>
<url>MingXing/ZhangNaLa.htm</url>
<color>green</color>
</item>
<item>
<name>張韶涵</name>
<url>MingXiang/ZhangShaoHan.htm</url>
<color>grey</color>
</item>
<item>
<name>張靚穎</name>
<url>MingXing/ZhangLiangYin.htm</url>
<color>black</color>
</item>
<item>
<name>李宇春</name>
<url>MingXing/LiYuChun.htm</url>
<color>yellow</color>
</item>
<item>
<name>徐若瑄</name>
<url>MingXing/XuLuXuan.htm</url>
<color>pink</color>
</item>
</root>
下面使用PULL解析方式對上述XML格式資料進行解析:
/**
* @param mXML2
*/
private void parseXML2(String mXML2) {
List<Star> list = null;
Star star = null;
//XMLPullParser.setInput()方法接收InputStream型別,故首先將String型別的XML資料轉換成InputStream型別
InputStream is = new ByteArrayInputStream(mXML2.getBytes());
XmlPullParser xpp = Xml.newPullParser();
try {
//XMLPullParser.setInput()方法接收InputStream型別
xpp.setInput(is, "UTF-8");
//獲取標籤型別
int type = xpp.getEventType();
//若未讀到最後的結束標籤,則不停遍歷每個標籤及其內容
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
//若為XML檔案起始標籤,則例項化List物件
case XmlPullParser.START_DOCUMENT:
list = new ArrayList<>();
break;
//若讀到每項的起始標籤
case XmlPullParser.START_TAG:
//起始標籤為"item"
if ("item".equals(xpp.getName())) {
//例項化Star物件
star = new Star();
}
// 起始標籤為"name"
else if ("name".equals(xpp.getName())) {
//後移一項
xpp.next();
//此時指向"name"標籤的內容,將該內容設定到建立的Star物件中
star.setName(xpp.getText());
}
//起始標籤為"url"
else if ("url".equals(xpp.getName())) {
//後移一項
xpp.next();
//此時指向"url"標籤的內容,將該內容設定到建立的Star物件中
star.setUrl(xpp.getText());
}
//起始標籤為"color"
else if ("color".equals(xpp.getName())) {
//後移一項
xpp.next();
//此時指向"color"標籤的內容,將該內容設定到建立的Star物件中
star.setColor(xpp.getText());
}
break;
//若指向結束標籤
case XmlPullParser.END_TAG:
//結束標籤為"item"時,說明已讀完一個完整的Star物件,該Star的所有欄位已被賦值物件
if ("item".equals(xpp.getName())) {
//將該Star物件加入List集合中
list.add(star);
}
break;
default:
break;
}
//後移一項
type = xpp.next();
}
//在LogCat中列印結果
for (Star s : list) {
Log.i("XML2", s.toString());
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
在LogCat中的輸出結果如下所示: