第一行代码学习笔记第九章——使用网络技术
知識點目錄
- 9.1 WebView的用法
- 9.2 使用HTTP協議訪問網絡
* 9.2.1 使用HttpURLConnection
* 9.2.2 使用OkHttp
- 9.3 解析XML格式數據
* 9.3.1 Pull解析方式
* 9.3.2 SAX解析方式
- 9.4 解析JSON格式數據
* 9.4.1 使用JSONObject
* 9.4.2 使用GSON
- 9.5 網絡編程的最佳實踐
- 9.6 小結與點評
知識點回顧
9.1 WebView的用法
WebView的主要作用就是在自己應用程序中顯示網頁,借助它我們可以在應用程序中嵌入一個瀏覽器。
一般使用步驟如下:
在布局中使用WebView控件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><WebViewandroid:id="@+id/web_view"android:layout_width="match_parent"android:layout_height="match_parent"></WebView></LinearLayout>實現網頁跳轉
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);WebView webView = (WebView) findViewById(R.id.web_view);webView.getSettings().setJavaScriptEnabled(true); //支持JavaScript//當需要從一個網頁跳轉到另一個網頁時,希望目標網頁仍在當前WebView中顯示,而不是打開系統瀏覽器webView.setWebViewClient(new WebViewClient());webView.loadUrl("http://www.baidu.com"); //轉入要跳轉的網址}}添加網絡訪問權限
<uses-permission android:name="android.permission.INTERNET"/>效果圖:
在運行程序之前,需要確保手機或者模擬器是連網的。
WebView中已經幫我們做了如下步驟的封裝:
-
發送HTTP請求
-
接收服務響應
-
解析返回的數據
-
頁面展示
9.2 使用HTTP協議訪問網絡
HTTP協議的工作原理:
客戶端向服務器發送一條HTTP請求,服務器收到請求之后會返回一些數據給客戶端,然后客戶端再對這些數據進行解析和處理。
9.2.1 使用HttpURLConnection
Android原生發送HTTP請求的方式有兩種:
-
HttpClient
-
HttpURLConnection
但HttpClient存在API數量過多、擴展困難等缺點,Android團隊已經不建議我們使用HttpClient。在Android6.0系統中,HttpClient的功能已經被完全移除。
Android官方建議使用HttpURLConnection。
HttpURLConnection一般使用步驟:
1.布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/send_request"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Send Request"android:textAllCaps="false"/><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/response_text"android:layout_width="match_parent"android:layout_height="wrap_content" /></ScrollView></LinearLayout>ScrollView可以讓用戶以滾動的形式查看屏幕外的那部分內容。
2.使用示例代碼
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private TextView mResponseText;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button sendRequest = (Button) findViewById(R.id.send_request);mResponseText = (TextView) findViewById(R.id.response_text);sendRequest.setOnClickListener(this);}@Overridepublic void onClick(View v) {if (v.getId() == R.id.send_request) {sendRequestWithHttpURLConnection();}}private void sendRequestWithHttpURLConnection() {//開啟線程來發送網絡請求new Thread(new Runnable() {@Overridepublic void run() {HttpURLConnection connection = null;BufferedReader reader = null;try {URL url = new URL("https://www.baidu.com");connection = ((HttpURLConnection) url.openConnection());// 設置請求方式,默認為GETconnection.setRequestMethod("GET");// 設置連接超時connection.setConnectTimeout(8000);// 設置讀取超時connection.setReadTimeout(8000);// 獲取網絡的輸入流InputStream inputStream = connection.getInputStream();// 讀取輸入流中的數據reader = new BufferedReader(new InputStreamReader(inputStream));StringBuilder response = new StringBuilder();String line;while ((line = reader.readLine()) != null) {response.append(line);}showResponse(response.toString());} catch (IOException e) {e.printStackTrace();}}}).start();}private void showResponse(final String response) {runOnUiThread(new Runnable() {@Overridepublic void run() {//在這里進行UI操作,將結果顯示到界面上mResponseText.setText(response);}});} }因為Android是不允許在子線程中進行UI操作的,這里我們通過使用runOnUiThread()方法將線程切換到主線程,然后再更新UI元素。
3.添加權限
<uses-permission android:name="android.permission.INTERNET"/>4.Post請求
如果想要給服務器提交數據,只需要將HTTP請求方法改為POST,并在獲取輸入流之前把要提交的數據寫出即可。每條數據之間以鍵值對的形式存在,數據與數據之間用&符號隔開。如下所示:
connection.setRequestMethod("POST"); DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.writeBytes("username=admin&password=123456");效果圖:
9.2.2 使用OkHttp
OkHttp是Square公司開發的一個開源盛行的網絡通信開源庫。
OkHttp的項目主頁地址是:
https://github.com/square/okhttp可以在主頁看到當前最新的版本。
在使用OkHttp之前,需要先在app/build.gradle文件的dependencies閉包中添加如下內容:
dependencies {implementation("com.squareup.okhttp3:okhttp:4.2.2") }OkHttp具體用法如下:
get請求:
new Thread(new Runnable() {@Overridepublic void run() {try {//創建一個OkHttpClient實例OkHttpClient client = new OkHttpClient();//創建一個Request對象Request request = new Request.Builder().url("http://www.baidu.com").build();//創建Call對象,并調用它的execute()方法發送請求并獲取服務器返回的數據Response response = client.newCall(request).execute();String responseData = response.body().string();showResponse(responseData);} catch (IOException e) {e.printStackTrace();}} }).start();POST請求:
new Thread(new Runnable() {@Overridepublic void run() {try {OkHttpClient client = new OkHttpClient();RequestBody body = new FormBody.Builder().add("username", "admin").add("password", "123456").build();Request request = new Request.Builder().url("http://www.baidu.com").post(body).build();// 創建Call對象,并調用它的execute()方法發送請求并獲取服務器返回的數據Response response = client.newCall(request).execute();String responseData = response.body().string();} catch (Exception e) {e.printStackTrace();}} }).start();上面只對OkHttp的get和post進行簡單的使用,更多的使用還需要到具體項目中去體驗。
9.3 解析XML格式數據
解析XML格式的數據有很多種,我們這里主要學習下Pull解析和SAX解析。
9.3.1 Pull解析方式
具體用法如下:
private void parseXMLWithPull(String xmlData) {try {//獲取一個XmlPullParserFactory實例對象XmlPullParserFactory factory = XmlPullParserFactory.newInstance();//通過XmlPullParserFactory實例對象獲得一個XmlPullParser對象XmlPullParser xmlPullParser = factory.newPullParser();//將XML數據設置進去xmlPullParser.setInput(new StringReader(xmlData));//通過getEventType()得到當前的解析事件int eventType = xmlPullParser.getEventType();String id = "";String name = "";String version = "";//開始解析,如果當前的解析事件不等于XmlPullParser.END_DOCUMENT,則表示解析還沒完成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)) {Log.d("MainActivity", "id is = " + id);Log.d("MainActivity", "name is = " + name);Log.d("MainActivity", "version is = " + version);}break;}default:break;}eventType = xmlPullParser.next();}} catch (Exception e) {e.printStackTrace();} }9.3.2 SAX解析方式
SAX解析比Pull解析復雜一些,但在語義方面會更加清楚。
具體用法如下:
第一步:新建一個類繼承自DefaultHandler
public class ContentHandler extends DefaultHandler {private String nodeName;private StringBuilder id;private StringBuilder name;private StringBuilder version;//開始XML解析時調用@Overridepublic void startDocument() throws SAXException {id = new StringBuilder();name = new StringBuilder();version = new StringBuilder();}//開始解析某個節點時調用@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {// 記錄當前節點nodeName = localName;}//獲取去節點中內容的時候調用@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {// 根據當前的節點名判斷將內容添加到哪一個StringBuilder對象中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);}}//完成解析某個節點的時候調用@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {if ("app".equals(localName)) {Log.d("ContentHandler", "id is = " + id.toString().trim());Log.d("ContentHandler", "name is = " + name.toString().trim());Log.d("ContentHandler", "version is = " + version.toString().trim());// 最后要將StringBuilder清空掉id.setLength(0);name.setLength(0);version.setLength(0);}}//完成整個XML解析時調用@Overridepublic void endDocument() throws SAXException {super.endDocument();} }第二步:開始解析
private void parseXMLWithSAX(String xmlData) {try {//獲取一個SAXParserFactory對象SAXParserFactory factory = SAXParserFactory.newInstance();//獲取一個XMLReader對象XMLReader xmlReader = factory.newSAXParser().getXMLReader();//new一個ContentHandler對象ContentHandler handler = new ContentHandler();//將ContentHandler的實例設置到XMLReader中xmlReader.setContentHandler(handler);//開始執行解析xmlReader.parse(new InputSource(new StringReader(xmlData)));} catch (Exception e) {e.printStackTrace();} }9.4 解析JSON格式數據
相比于XML,JSON數據的主要優勢是體積更小,在網上傳輸的時候可以更省流量。但缺點在于,JSON語義性較差,看起來不如XML直觀。
解析JSON數據的方法有很多種,我們主要學習官方提供的JSONObject和谷歌開源庫GSON。
9.4.1 使用JSONObject
具體用法如下:
private void parseJSONWithJSONObject(String jsonData) {try {JSONArray jsonArray = new JSONArray(jsonData);for (int i = 0; i < jsonArray.length(); i++) {JSONObject jsonObject = jsonArray.getJSONObject(i);String id = jsonObject.getString("id");String name = jsonObject.getString("name");String version = jsonObject.getString("version");Log.d("MainActivity", "id is " + id);Log.d("MainActivity", "name is " + name);Log.d("MainActivity", "version is " + version);}} catch (Exception e) {e.printStackTrace();} }9.4.2 使用GSON
第一步:添加GSON庫的依賴
在app/build.gradle文件的dependencies閉包中添加如下內容:
dependencies {implementation 'com.google.code.gson:gson:2.8.6' }第二步:編寫json數據的實例類
public class App {private String id;private String name;private String version;public void setId(String id) {this.id = id;}public void setName(String name) {this.name = name;}public void setVersion(String version) {this.version = version;}public String getId() {return id;}public String getName() {return name;}public String getVersion() {return version;} }當然這一步可以使用GsonFormat這個插件去完成!!!
第三步:具體解析
private void parseJSONWithGSON(String jsonData) {Gson gson = new Gson();//JSON數據是對象型App app = gson.fromJson(jsonData, App.class);//JSON數據是數組型List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>(){}.getType()); }這里根據JSON數據的不同類型,解析方式稍微有點不同。
9.5 網絡編程的最佳實踐
使用HttpURLConnection網絡請求的工具類。
第一步:定義個接口
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 listener) {new Thread(new Runnable() {@Overridepublic void run() {HttpURLConnection connection = null;try {URL url = new URL(address);connection = (HttpURLConnection) url.openConnection();connection.setRequestMethod("GET");connection.setConnectTimeout(8000);connection.setReadTimeout(8000);connection.setDoInput(true);connection.setDoOutput(true);InputStream in = connection.getInputStream();BufferedReader reader = new BufferedReader(new InputStreamReader(in));StringBuilder response = new StringBuilder();String line;while ((line = reader.readLine()) != null) {response.append(line);}if (listener != null) {//回調onFinish()方法listener.onFinish(response.toString());}} catch (Exception e) {e.printStackTrace();if (listener != null) {//回調onError()方法listener.onError(e);}} finally {if (connection != null) {connection.disconnect();}}}}).start();} }第三步:使用工具類
HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {@Overridepublic void onFinish(String response) {// 在這里根據返回內容執行具體的邏輯}@Overridepublic void onError(Exception e) {// 在這里對異常情況進行處理} });使用OkHttp網絡請求的工具類。
第一步:定義工具類
public class HttpUtil {public static void sendOkHttpRequest(String address, okhttp3.Callback callback) {OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url(address).build();client.newCall(request).enqueue(callback);} }這里newCall()后面調用的是enqueue()方法,enqueue()方法內部已經幫我們開啟了子線程。
第二步:使用工具類
HttpUtil.sendOkHttpRequest("address", new okhttp3.Callback() {@Overridepublic void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {//得到服務器返回的具體內容String responseData = response.body().string();}@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {//在這里對異常情況進行處理} });9.6 小結與點評
本章主要學習了在Android中使用HTTP協議來進行網絡交互。使用HttpURLConnection和OkHttp來發送HTTP請求。然后學習了XML和JSON格式數據的解析方式。
非常感謝您的耐心閱讀,希望我的文章對您有幫助。歡迎點評、轉發或分享給您的朋友或技術群。
總結
以上是生活随笔為你收集整理的第一行代码学习笔记第九章——使用网络技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第一行代码学习笔记第八章——运用手机多媒
- 下一篇: 第一行代码学习笔记第十章——探究服务