Android實戰開發---請求介面擷取資料
上文中我們看過了項目的整體架構,趁著寫介面的間隙,和大家一起研究一下讀取介面的類:XMLTool.java。
說實話,自己的項目名字感覺起的都不怎麼好,XMLTool很容易讓人以為是與XML有關的工具,誰也不會想到是請求介面的一系列方法,這裡以後肯定要改進,這回我們還是以程式碼分析為主。
在這個類中,我們有幾個主要的方法,分別是GetXmlValue、PostXmlValue、DeleteXmlValue、UploadImagFile、ReturnXMLValue、DownloadFile2SDCard、GetInputStreamFromUrl這七個方法。基本上常用的請求操作都用到了,從名字應該可以看出大概的作用,下面我們一一說明,並指出其中的一些主要代碼。
我們的介面是REST格式,也就是有四種狀態get擷取資料、post新增/修改資料、put修改資料(未用)、delete刪除資料。
1. GetXmlValue
這個方法很明顯,是用來進行get提交並取得資料。使用的是比較常用的方法,大家看看代碼也就明白了:
StringBuffer sbResult = new StringBuffer(); // 建立一個http用戶端 HttpClient client = new DefaultHttpClient(); // 建立一個GET請求 HttpGet httpGet = new HttpGet(url); // 向伺服器發送請求並擷取伺服器返回的結果 HttpResponse response = null; // 返回的結果可能放到InputStream,http Header中等。 InputStream inputStream = response.getEntity().getContent(); // 讀取內容 BufferedReader br = new BufferedReader(new InputStreamReader( inputStream, "utf-8")); String data = ""; if (sbResult.toString().equalsIgnoreCase("")) { while ((data = br.readLine()) != null) { sbResult.append(data); } } inputStream.close();
這段代碼應該是網路上比較常見的了,也不用我過多的解釋了。
2. PostXmlValue
這個是使用post提交資料,用於新增、修改資料。其中主要是參數的添加,這裡我從外面傳入一個HashMap並轉為List<BasicNameValuePair>,代碼如下:
…… // 建立一個POST請求 HttpPost httpPost = new HttpPost(url); //添加post參數 List<BasicNameValuePair> dataList = new ArrayList<BasicNameValuePair>(); Iterator<Map.Entry<String, String>> i = param.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, String> o = (Map.Entry<String, String>) i.next(); dataList.add(new BasicNameValuePair(o.getKey().toString(), o.getValue().toString())); } HttpEntity entity = entity = new UrlEncodedFormEntity(dataList, "UTF-8"); httpPost.setEntity(entity); ……
3. DeleteXmlValue
Delete方法就比較簡單了,和get方法類似,不過就是將HttpGet改成HttpDelete對象而已。
// 建立一個Delete請求 HttpDelete httpDelete = new HttpDelete();
4. UploadImagFile
這是一個上傳圖片的方法,主要是上傳一些小的圖片檔案之類,用的也是比較普遍的二進位流的上傳方式。
將檔案讀取到一個FileInputStream對象中,然後通過DataOutputStream的write方法寫入請求中,這裡要注意的是一些參數的添加,比如上傳的檔案名稱怎麼定義之類的。
sb1.append("Content-Disposition: form-data; name=\"do_img\"; filename=\""+ file.getName() + "\"" + LINEND); outStream.write(sb1.toString().getBytes());
其實這段代碼自己也是似懂非懂,我們就留作最後的提高部分供大家探討,也希望有高手能將這段代碼全標上注釋供大家理解。
5. ReturnXMLValue
這個方法就是在上面的GetXmlValue中的// 返回的結果可能放到InputStream,http Header中等。後面那一段,因為每個請求都會用到,所以提了出來。
6. DownloadFile2SDCard
這個方法應該看名字能看出來,下載檔案到手機卡上。
其中FileTool是另外一個工具類,用於一些檔案的建立、尋找方面的工作,我們以後再介紹,這裡只是取得inputstream後調用FileTool中的方法來進行操作,所以就不多介紹,留待以後介紹FileTool類時再說。
7. GetInputStreamFromUrl
擷取串連inputstream方法,返回的是conn.getInputStream()。
這就是我用來請求介面的類,其實還是比較粗糙的,但準系統都沒問題,而且在上一版本的使用中也並沒有出現過什麼問題,因此還算是比較好用的一個工具類。下面附上全部的代碼供參考。
package hb.hbwb.tools;/** * @name XML資料處理類 * @author zhang.yue * @create_date 20110512 * @last_edit_author zhang.yue * @last_edit_date 20111115 * @remark * @edit_remark 最佳化代碼 */import hb.hbwb.R;import hb.hbwb.finals.SystemFinals;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.HttpURLConnection;import java.net.URI;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.HttpDelete;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.message.BasicNameValuePair;import android.content.Context;public class XMLTool {/** * 根據請求url擷取資訊--GET方法 * * @param url 連結地址 * @param activity 頁面context * @return XML String */public static StringBuffer GetXmlValue(String url, Context activity) {StringBuffer sbResult = new StringBuffer();// 建立一個http用戶端HttpClient client = new DefaultHttpClient();// 建立一個GET請求HttpGet httpGet = new HttpGet(url);// 向伺服器發送請求並擷取伺服器返回的結果HttpResponse response = null;try {response = client.execute(httpGet);//擷取Stream到字元sbResult = ReturnXMLValue(sbResult, response);} catch (Exception e) {System.out.println(e.getMessage());// 無法訪問伺服器,載入錯誤資訊sbResult.append(activity.getText(R.string.server_noservice_xml).toString()); }return sbResult;}/** * POST請求 * * @param url 連結地址 * @param activity 頁面context * @param param 參數 * @return XML String */public static StringBuffer PostXmlValue(String url, Context activity,HashMap<String, String> param) {StringBuffer sbResult = new StringBuffer();// 建立一個http用戶端HttpClient client = new DefaultHttpClient();// 建立一個POST請求HttpPost httpPost = new HttpPost(url);//添加post參數List<BasicNameValuePair> dataList = new ArrayList<BasicNameValuePair>();Iterator<Map.Entry<String, String>> i = param.entrySet().iterator();while (i.hasNext()) {Map.Entry<String, String> o = (Map.Entry<String, String>) i.next();dataList.add(new BasicNameValuePair(o.getKey().toString(), o.getValue().toString()));}HttpEntity entity = null;try {entity = new UrlEncodedFormEntity(dataList, "UTF-8");httpPost.setEntity(entity);// 向伺服器發送請求並擷取伺服器返回的結果HttpResponse response = client.execute(httpPost);sbResult = ReturnXMLValue(sbResult, response);} catch (Exception e) {System.out.println(e.getMessage());sbResult.append(activity.getText(R.string.server_noservice_xml).toString()); // 無法訪問伺服器}return sbResult;}/** * Delete請求 * * @param url 連結地址 * @param activity 頁面context * @return XML String */public static StringBuffer DeleteXmlValue(String url, Context activity) {StringBuffer sbResult = new StringBuffer();// 建立一個http用戶端HttpClient client = new DefaultHttpClient();// 建立一個Delete請求HttpDelete httpDelete = new HttpDelete();// 向伺服器發送請求並擷取伺服器返回的結果HttpResponse response = null;try {httpDelete.setURI(new URI(url));response = client.execute(httpDelete);sbResult = ReturnXMLValue(sbResult, response);} catch (Exception e) {System.out.println(e.getMessage());sbResult.append(activity.getText(R.string.server_noservice_xml).toString()); // 無法訪問伺服器}return sbResult;}/** * 圖片上傳 * * @param actionUrl 連結地址 * @param imageFilePath 圖片路徑 * @param activity 頁面context * @return XML String */public static String UploadImagFile(String actionUrl,String imageFilePath, Context activity) {String BOUNDARY = java.util.UUID.randomUUID().toString();String PREFIX = "--", LINEND = "\r\n";String MULTIPART_FROM_DATA = "multipart/form-data";try {URL url = new URL(actionUrl);HttpURLConnection con = (HttpURLConnection) url.openConnection();con.setReadTimeout(5 * 1000); // 緩衝的最長時間con.setDoInput(true);// 允許輸入con.setDoOutput(true);// 允許輸出con.setUseCaches(false); // 不允許使用緩衝con.setRequestMethod("POST");con.setRequestProperty("connection", "keep-alive");con.setRequestProperty("Charsert", "UTF-8");con.setRequestProperty("Content-Type", MULTIPART_FROM_DATA+ ";boundary=" + BOUNDARY);DataOutputStream outStream = new DataOutputStream(con.getOutputStream());File file = new File(imageFilePath);FileInputStream fStream = new FileInputStream(file);int bufferSize = 1024;byte[] buffer = new byte[bufferSize];StringBuilder sb1 = new StringBuilder();sb1.append(PREFIX);sb1.append(BOUNDARY);sb1.append(LINEND);String ext = file.getName().substring(file.getName().lastIndexOf(".") + 1);String ctypeString = StringTool.Zch_GetUpImageExt(ext);sb1.append("Content-Disposition: form-data; name=\"do_img\"; filename=\""+ file.getName() + "\"" + LINEND);sb1.append("Content-Type: " + ctypeString + "; charset=" + SystemFinals.CHARSET+ LINEND);sb1.append(LINEND);outStream.write(sb1.toString().getBytes());int length = -1;while ((length = fStream.read(buffer)) != -1) {outStream.write(buffer, 0, length);}outStream.write(LINEND.getBytes());fStream.close();// 請求結束標誌byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINEND).getBytes();outStream.write(end_data);outStream.flush();int res = con.getResponseCode();StringBuffer b = new StringBuffer();if (res == 200) {InputStream is = con.getInputStream();int ch;while ((ch = is.read()) != -1) {b.append((char) ch);}}outStream.close();return b.toString();} catch (Exception e) {return "";}}/** * 讀取返回的資訊 * * @param sbResult 串連用字元 * @param response 資料response * @return XML String * @throws Exception IllegalStateException或IOException異常 */private static StringBuffer ReturnXMLValue(StringBuffer sbResult,HttpResponse response) throws Exception {// 返回的結果可能放到InputStream,http Header中等。InputStream inputStream = response.getEntity().getContent();// 讀取內容BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));String data = "";if (sbResult.toString().equalsIgnoreCase("")) {while ((data = br.readLine()) != null) {sbResult.append(data);}}inputStream.close();return sbResult;}/** * 下載檔案並儲存到記憶卡方法 * @param urlString 檔案地址 * @param path 儲存路徑 * @param fileName 檔案名稱 * @return 0成功,1已存在,-1發生錯誤 */public int DownloadFile2SDCard(String urlString,String path,String fileName){InputStream inputStream = null;try {FileTool fileTool = new FileTool();if(fileTool.IsFileExist(fileName, path)){return 1;}else{inputStream = GetInputStreamFromUrl(urlString);File resultFile = fileTool.Write2SDFromInput(path, fileName, inputStream);if(resultFile==null){return -1;}}} catch (Exception e) {System.out.println(e.getMessage());return -1;}finally{try {inputStream.close();} catch (Exception e) {System.out.println(e.getMessage());}}return 0;}/** * 擷取串連inputstream方法 * @param urlStr 串連地址 * @return inpustream流 * @throws IOException */private InputStream GetInputStreamFromUrl(String urlStr) throws IOException{URL url = new URL(urlStr);HttpURLConnection conn = (HttpURLConnection) url.openConnection();return conn.getInputStream();}}
======================================================
提高: 1. UploadImagFile注釋
2.在這個類中,我將Expection全部使用Expection一個來拋出,而不是分成N個詳細的Catch來拋出,這樣會不會對效能造成影響,或者說哪種效能更優,它們的優缺點是什嗎?
(提高部分將會提出一些自己感覺到的問題,當然有朋友提出的好問題我也會放上來,然後如果有回答的我們就將好答案也放上來看看再供大家一起討論學習)