01. WebView
- 使用 WebView 加載網頁
private void initWebView() { wb_net.getSettings().setJavaScriptEnabled(true);// 支援 JavaScript 腳本 wb_net.setWebViewClient(new WebViewClient());// 網頁跳轉仍在目前浏覽器 wb_net.loadUrl("http://www.baidu.com");// 加載網頁 }
- 方法
-
方法作用,當需要從一個網頁跳轉另一個網頁時,目标網頁仍然在目前 WebView 中顯示,而不是打開系統浏覽器。setWebViewClient()
-
- 網絡權限
<uses-permission android:name="android.permission.INTERNET" />
02. 使用 HTTP 協定通路網絡
-
工作原理
用戶端向伺服器發出一條 HTTP 請求,伺服器收到請求之後傳回一些資料給用戶端,然後用戶端再對這些資料進行解析和處理就可以了。
- 使用 HttpURLConnection
private void sendRequestWithHttpURLConnection() { new Thread(new Runnable() {// 網絡請求耗時操作放在子線程中 @Override public void run() { HttpURLConnection httpURLConnection = null;// 連接配接對象 BufferedReader bufferedReader = null;// 資料讀取流 try { URL url = new URL("http://www.baidu.com");// URL 對象 httpURLConnection = (HttpURLConnection) url.openConnection();// 打開連接配接 httpURLConnection.setRequestMethod("GET");// 設定網絡請求模式 httpURLConnection.setConnectTimeout();// 設定連接配接逾時時間 httpURLConnection.setReadTimeout();// 設定資料讀取逾時時間 InputStream inputStream = httpURLConnection.getInputStream();// 擷取資料讀取流 bufferedReader = new BufferedReader(new InputStreamReader(inputStream));// 對流封裝提供效率 StringBuilder response = new StringBuilder();// 請求結果 String line; while ((line = bufferedReader.readLine()) != null) { response.append(line);// 從資料讀取流中讀取資料 } showResponse(response.toString());// 進行界面展示 } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close();// 關閉資料流 } catch (IOException e) { e.printStackTrace(); } } if (httpURLConnection != null) { httpURLConnection.disconnect();// 關閉網絡連接配接 } } } }).start(); } private void showResponse(final String response) { runOnUiThread(new Runnable() {// 界面重新整理的工作必須放在主線程中 @Override public void run() { tv_result.setText(response); } }); }
- 小細節
- 網絡請求模式有
和GET
等,其中POST
表示希望從伺服器那裡擷取資料,而GET
表示希望送出資料給伺服器。POST
- 設定網絡連接配接逾時時間
- 設定資料讀取逾時時間
- 設定請求頭資料
- 網絡請求等耗時操作需要放在子線程
- 界面控件重新整理需要放在主線程
- 網絡請求模式有
03. 使用 OKHttp
- 添加依賴
- 使用 OKHttp
private void sendRequestWithOkHttp() { new Thread(new Runnable() {// 網絡請求耗時操作放在子線程中 @Override public void run() { try { OkHttpClient okHttpClient = new OkHttpClient();// OK 用戶端 RequestBody requestBody = new FormBody.Builder() .add("userName", "admin") .add("passWord", "232323") .build();// 參數封裝 Request request = new Request.Builder() .url("https://www.baidu.com") .post(requestBody)// 用 POST 請求攜帶參數 .build(); Response response = okHttpClient.newCall(request).execute();// 執行請求傳回響應對象 String responseContent = response.body().string();// 從響應對象中擷取字元串 showResponse(responseContent);// 進行界面展示 } catch (IOException e) { e.printStackTrace(); } } }).start(); }
04. Pull 方式解析 XML
- XML 格式資料内容
<apps> <app> <id>1</id> <name>Google</name> <version>1.1</version> </app> <app> <id>2</id> <name>FaceBook</name> <version>1.2</version> </app> <app> <id>3</id> <name>Twitter</name> <version>1.3</version> </app> </apps>
- 使用 Pull 解析
private void parseXMLWithPull(String responseContent) { try { XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();// 擷取工廠執行個體 XmlPullParser xmlPullParser = xmlPullParserFactory.newPullParser();// 工廠執行個體擷取一個解析器 xmlPullParser.setInput(new StringReader(responseContent));// 以流的方式給解析器設定資料源 int eventType = xmlPullParser.getEventType();// 擷取事件類型 String id = ""; String name = ""; String version = ""; while (eventType != XmlPullParser.END_DOCUMENT) {// 不是文檔結尾 String nodeName = xmlPullParser.getName();// 擷取節點名稱 switch (eventType) {// 事件類型 case XmlPullParser.START_TAG:// 标簽開始 if ("id".equals(nodeName)) {// 判斷标簽名稱 id = xmlPullParser.nextText();// 擷取标簽中的内容 } else if ("name".equals(nodeName)) { name = xmlPullParser.nextText(); } else if ("version".equals(nodeName)) { version = xmlPullParser.nextText(); } break; case XmlPullParser.END_TAG:// 标簽結束 if ("app".equals(nodeName)) { LogUtils.e("id = " + id + " name = " + name + " version = " + version + "\n"); } break; default: break; } eventType = xmlPullParser.next();// 擷取下一個事件 } } catch (Exception e) { e.printStackTrace(); } }
- 重要方法
-
方法擷取目前節點名稱getName()
-
方法擷取目前節點内的具體内容nextText()
-
05. SAX 方式解析 XML
- 自定義 SaxHandler 繼承自 DefaultHandler
/** * 9.3.2 SAX 解析方式 * * @author JustDo23 * @since 2017年08月01日 */ public class SaxHandler extends DefaultHandler { private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder version; /** * 開始解析文檔 * * @throws SAXException 異常 */ @Override public void startDocument() throws SAXException { super.startDocument(); id = new StringBuilder(); name = new StringBuilder(); version = new StringBuilder(); } /** * 開始解析節點 * * @param uri 命名空間字元串[可能為空] * @param localName 節點名稱[可能為空] * @param qName 限定名[可能為空] * @param attributes 屬性 * @throws SAXException 異常 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); nodeName = localName;// 目前節點名稱 } /** * 擷取節點内容[可能會調用多次,一些換行符也被當作内容解析出來] * * @param ch 位元組數組 * @param start 起始位置 * @param length 有效長度 * @throws SAXException */ @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); if ("id".equals(nodeName)) { id.append(ch, start, length); } else if ("name".equals(nodeName)) { name.append(ch, start, length); } else if ("version".equals(nodeName)) { version.append(ch, start, length); } } /** * 完成節點解析 * * @param uri 命名空間字元串[可能為空] * @param localName 節點名稱[可能為空] * @param qName 限定名[可能為空] * @throws SAXException 異常 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if ("app".equals(localName)) { LogUtils.e("id = " + id.toString() + " name = " + name.toString() + " version = " + version.toString() + "\n"); id.setLength(); name.setLength(); version.setLength(); } } /** * 完成文檔解析 * * @throws SAXException 異常 */ @Override public void endDocument() throws SAXException { super.endDocument(); LogUtils.e("SAX 解析結束"); } }
- 使用 SAX 解析
private void parseXMLWithSAX(String responseContent) { try { SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();// 擷取工廠執行個體 XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();// 利用工廠擷取解析器後擷取XML讀取器 SaxHandler saxHandler = new SaxHandler();// 執行個體化自定義的 Handler xmlReader.setContentHandler(saxHandler);// 讀取器設定 Handler xmlReader.parse(new InputSource(new StringReader(responseContent)));// 開始解析 } catch (Exception e) { e.printStackTrace(); } }
06. 解析 JSON 格式資料
- json 格式資料内容
[ { "id": "4", "name": "Chrome", "version": "1.4" }, { "id": "5", "name": "Safari", "version": "1.5" }, { "id": "6", "name": "Firefox", "version": "1.6" } ]
- 使用 JSONObject
private void parseJson(String responseContent) { try { JSONArray jsonArray = new JSONArray(responseContent);// 擷取數組對象 for (int i = ; i < jsonArray.length(); i++) {// 對數組進行循環 JSONObject jsonObject = jsonArray.getJSONObject(i);// 挨個擷取JSONObject String id = jsonObject.getString("id"); String name = jsonObject.getString("name"); String version = jsonObject.getString("version"); LogUtils.e("id = " + id + " name = " + name + " version = " + version + "\n"); } } catch (Exception e) { e.printStackTrace(); } }
- 使用 Gson
- 添加依賴
- 定義實體類
- 使用 Gson
private void parseJsonWithGson(String responseContent) { Gson gson = new Gson();// 執行個體化對象 List<Product> productList = gson.fromJson(responseContent, new TypeToken<List<Product>>() {}.getType());// 解析數組方法 for (Product product : productList) { LogUtils.e("id = " + product.getId() + " name = " + product.getName() + " version = " + product.getVersion() + "\n"); } }
07. 最佳實踐
- 回調接口
public interface HttpCallBackListener { /** * 網絡請求完成時回調 * * @param response 傳回資料 */ void onFinish(String response); /** * 網絡請求出現錯誤 * * @param e 異常 */ void onError(Exception e); }
- 工具類封裝
public class HttpUtil { public static void sendHttpRequest(final String address, final HttpCallBackListener httpCallBackListener) { new Thread(new Runnable() { @Override public void run() { HttpURLConnection httpURLConnection = null; try { URL url = new URL(address); httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(); httpURLConnection.setReadTimeout(); httpURLConnection.setDoInput(true); httpURLConnection.setDoOutput(true); InputStream inputStream = httpURLConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { response.append(line); } if (httpCallBackListener != null) { httpCallBackListener.onFinish(response.toString()); } } catch (Exception e) { if (httpCallBackListener != null) { httpCallBackListener.onError(e); } } finally { if (httpURLConnection != null) { httpURLConnection.disconnect(); } } } }).start(); } public static void sendOkHttpRequest(String address, okhttp3.Callback callback) { OkHttpClient okHttpClient = new OkHttpClient(); Request request = new Request.Builder() .url(address) .build(); okHttpClient.newCall(request).enqueue(callback);// 開啟子線程 } }
- 注意線程問題
08. 小結
- 對 WebView 進行更詳細的學習使用。
- 對 HTTP 協定進行更詳細的學習使用。
- 如果可以那就看看 OKHttp 等的源碼解析。
- 其他第三方網絡請求架構簡單了解。