1. 程式人生 > >安卓開發之解析XML和JSON格式資料

安卓開發之解析XML和JSON格式資料

參考書作者:郭霖

我會將所學的知識簡單記錄下來以便於大家快速查閱資料,另外郭霖大俠沒有提到的東西我也會作出補充

我們

通常情況下,每個需要訪問網路的應用程式都會有一個自己的伺服器,我們可以向伺服器提交資料,也可以從伺服器

上獲取資料。在網路上傳輸資料時最常用的格式用兩種:XML和JSON

解析XML格式資料

我們就搭建一個最簡單的Web伺服器,在這個伺服器上提供一段XML文字,然後我們程式訪問這個伺服器,再對得到的XML文字

進行解析

大家先下載好Apache伺服器(百度搜索或者直接在官網上下載),一直預設安裝就行了,

下面開啟瀏覽器驗證一下


接下來在你的安裝目錄Apache\htdocs目錄下新建一個名為get_data.xml的檔案,編輯這個檔案

<apps>
	<app>
		<id>1</id>
		<name>Google Maps</name>
		<version>1.0</version>
	</app>
	<app>
		<id>2</id>
		<name>Chrome</name>
		<version>2.1</version>
	</app>
	<app>
		<id>3</id>
		<name>Google Play</name>
		<version>2.3</version>
	</app>
</apps>

在瀏覽器訪問http://127.0.0.1/get_data.xml可以看到內容 現在我們就解析這個返回的XML檔案

為了方便起見,我們在下面這個專案上進行解析XML

比較常用的解析XML方法有Pull解析和SAX解析當然還有DOM解析,這裡我們只介紹前兩種解析

Pull和SAX解析方式

Pull解析我們只需要新增一個私有方法,然後在sendRequestWithOkHttp方法中呼叫parserXMLWithPull方法

SAX解析我們需要建立一個新的類ContentHandler,這個類繼承自DefaultHandler類,並重寫父類的5個方法

我們修改MainActivity中的程式碼

package com.gougoucompany.clarence.networktest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.xml.parsers.SAXParserFactory;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    TextView responseText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendRequest = (Button) findViewById(R.id.send_request);
        responseText = (TextView) findViewById(R.id.response_text);
        sendRequest.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if(v.getId() == R.id.send_request) {
            //sendRequestWithURLConnection();

            /*今天,我們有許多出色的網路通訊庫都可以替代原生的HttpURLConnection,而其中OkHttp是比較出色的一個
            * 現在已經成為了廣大安卓開發者首選的網路通訊庫 OkHttp的專案主頁地址是: http://github.com/square/okhttp
            * 可以檢視最新的版本
            * 我們要現在app/build.gradle檔案中加入OkHttp庫的依賴,會自動下載兩個庫OkHttp和Okio庫
            * 我們來看OkHttp的使用步驟
            * 1. 建立OkHttpClient例項
            * 2. 建立一個Request物件
            * 3. 使用OkHttpClient的newCall()方法建立一個Call物件,並呼叫它的execute()方法來發送請求和接受伺服器返回的資料
            * 4. 使用Response物件接受伺服器返回的資料 然後使用response.body().string()方法獲得具體的內容
            * 這種是使用"GET"方法提交請求
            *
            * 下來看如何使用"POST"方法提交請求
            * 先構建一個RequestBody物件來存放待提交的資料
            * RequestBody requestBody = new FormBody.Builder()
            * .add("username", "admin")
            * .add("password", "123456")
            * .builder();
            * 然後在Request.Builder構造器呼叫post()方法將RequestBody物件傳入
            * Request request = new Request.Builder()
            * .url("http://www.baidu.com")
            * .post(requestBody)
            * .build();後面的都一樣了*/
            sendRequestWithOkHttp();
        }
    }

    private void sendRequestWithOkHttp() {
        //開啟執行緒來發起網路請求
        new Thread(new Runnable () {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            //指定訪問的伺服器地址是電腦本機
                            .url("http://10.0.2.2/get_data.xml") //通過url()方法設定目標的網路地址
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    Log.d("MainActivity", responseData);
                    //showResponse(responseData);
                    parseXMLWithPull(responseData);
                    //parseXMLWithSAX(responseData);
                } catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void parseXMLWithSAX(String xmlData) {
        /*parseXMLWithSAX()方法中先是建立了一個SAXParserFactory物件,然後
        * 再獲取到XMLReader物件,接著將我們編寫的ContentHandler的例項設定到XMLReader中
        * ,最後呼叫parse()方法執行解析就好了*/
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            XMLReader xmlReader = factory.newSAXParser().getXMLReader();
            ContentHandler handler = new ContentHandler();
            //將ContentHandler例項設定到xmlReader中
            xmlReader.setContentHandler(handler);
            //開始執行解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    private void parseXMLWithPull(String xmlData) {
        try {
            //獲得一個XmlPullParserFactory例項
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            //得到XmlPullParser物件
            XmlPullParser xmlPullParser = factory.newPullParser();
            //呼叫xmlPullParser的setInput方法將伺服器返回的XML資料傳入開始解析
            xmlPullParser.setInput(new StringReader(xmlData));
            //獲得當前的解析事件
            int eventType = xmlPullParser.getEventType();
            String id = "";
            String name = "";
            String version = "";
            while (eventType != XmlPullParser.END_DOCUMENT) {
                //getName()方法獲得當前節點的名字
                String nodeName = xmlPullParser.getName();
                //如果發現節點名等於id,name或version,就呼叫nextText()方法來獲取節點內具體的內容
                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;
                    }
                    //完成解析某個節點就將id,name,version全都打印出來
                    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();
        }
    }

    private void sendRequestWithURLConnection() {
        //開啟執行緒來發起網路請求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try{
                    URL url = new URL("https://www.baidu.com");
                    //獲取HttpURLConnection例項
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    //設定連線超時
                    connection.setConnectTimeout(8000);
                    //設定讀取超時的毫秒數
                    connection.setReadTimeout(8000);
                    //獲取到伺服器返回的輸入流,位元組輸入流InputStream物件
                    InputStream in = connection.getInputStream();
                    //下面對獲取到的輸入流進行讀取
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    showResponse(response.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if(reader != null) {
                        try{
                            reader.close();
                        } catch(IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(connection != null) {
                        connection.disconnect(); //將Http連線關閉掉
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //在這裡進行UI操作,將結果顯示到介面上
                responseText.setText(response);
            }
        });
    }
}

新建類ContentHandler

package com.gougoucompany.clarence.networktest;

import android.util.Log;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * Created by Clarence on 2018/4/13.
 * Sax解析是一種特別常用的xml解析方式,雖然用法比Pull解析要複雜一些,但在
 * 語義方面會更加清楚
 * 通常情況下我們都會新建一個類繼承自DefaultHandler,並重寫父類的5個方法
 */

public class ContentHandler extends DefaultHandler {

    private String nodeName;

    private StringBuilder id;

    private StringBuilder name;

    private StringBuilder version;

    //開始xml解析的時候呼叫
    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
        version = new StringBuilder();
    }

    //開始解析某個節點的時候呼叫
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        //記錄當前的節點名
        nodeName = localName;
    }

    //characters()方法會在獲取節點中的內容的時候呼叫
    //StringBuilder的append(char[], int offset, int len)方法將陣列從下標offset開始的len個字元依次新增到當前字串的末尾
    @Override
    public 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);
        }
    }

    //會在完成解析某個節點的時候呼叫
    @Override
    public 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清空掉 java.lang.StringBuilder.setLength(int newLength)來改變字元序列的長度
            id.setLength(0);
            name.setLength(0);
            version.setLength(0);
        }
    }

    //會在完成整個xml解析的時候呼叫
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

下面是解析伺服器傳送的xml檔案後得到的資訊,我們將它顯示到日誌Debug中


需要注意的是:模擬機訪問127.0.0.1都是訪問模擬器本身,你想在模擬器上訪問安裝模擬器的電腦,

那麼就使用Android內建的ip:10.0.2.2 另外記住要開啟模擬器網路開關

解析JSON格式資料

我們在Apache\htdocs目錄中新建一個get_data.json的檔案,然後編輯這個檔案,並加入如下JSON格式的內容

[{"id" : "5", "version" : "5.5", "name" : "Clash of Clans"},
{"id" : "6", "version" : "7.0", "name" : "Boom Beach"},
{"id" : "7", "version" : "3.5", "name" : "Clash Royale"}]
在瀏覽器中訪問http://127.0.0.1/get_data.json


解析JSON資料也有很多方法,可以使用官方提供的JSONObject,也可以使用谷歌的開源庫GSON。另外,一些第三方的

開源庫如Jackson、FastJSON等也非常不錯。這裡我們介紹前兩種

JSONObject解析 首先將伺服器返回的資料傳入到了一個JSONArray物件中,然後迴圈遍歷這個JSONArray,從中取出的每一個元素都是一個JSONObject物件,每個JSONObject物件中又會包含id,name和version這些資料。接下來只需要呼叫getString()

方法將這些資料取出,並打印出來即可。

要使用GJSON,必須在專案中新增GSON庫的依賴。編輯app/build.gradle檔案,在dependencies閉包中新增如下內容:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
    compile 'com.squareup.okhttp3:okhttp:3.10.0'
    compile 'com.google.code.gson:gson:2.7'
}

GSON庫可以將一段JSON格式的字串自動對映成一個物件。

eg: 比如一段JSON格式的資料 {"name" : "Tom", "age" : 20}

我們可以定義一個Person類,並加入name和age這兩個欄位

Gson gson= new Gson();

Person person = gson.fromJson(jsonData, Person.class);

如果需要解析的是一段JSON陣列會稍微麻煩一點,我們需要藉助TypeToken將期望解析的資料型別

傳入到fromJson()方法中

List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Persion>>(){}.getType());

fromJson中提供兩個引數,分別是json字串以及需要轉換成物件的型別

new TypeToken<List<People>>(){}.geType(),這個位置的引數是一個Type,表示是xx型別,但是Type是個

介面如下:

public interface Type {  
    /** 
     * Returns a string describing this type, including information 
     * about any type parameters. 
     * 
     * @implSpec The default implementation calls {@code toString}. 
     * 
     * @return a string describing this type 
     * @since 1.8 
     */  
    default String getTypeName() {  
        return toString();  
    }  
}  


new XXX();這樣是一個建構函式,但是介面是不能直接new的,所以這時用到了匿名內部類,實現介面稱為一種具體的型別

TypeToken,它是gson提供的資料型別轉換器,可以支援各種資料型別轉換,先呼叫TypeToken<T>的構造器得到匿名內部類,

再由該匿名內部類物件呼叫getType()方法得到想要轉換成的type,這裡type就是List<People>型別

我們先增加一個App類,並加入id、name和version這三個欄位,並自動生成getter和setter方法

package com.gougoucompany.clarence.networktest;

/**
 * Created by Clarence on 2018/4/14.
 */

public class App {

    private String id;

    private String name;

    private String version;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }
}

然後修改MainActivity中的程式碼

我們只要新增一個私有的方法,然後在這個方法完成解析任務

    //使用GSON開源庫解析json格式的資料
    private void parseJSONWithGSON(String jsonData) {
        Gson gson = new Gson();
        List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>(){}.getType());
        for (App app : appList) {
            Log.d("MainActivity", "id is " + app.getId());
            Log.d("MainActivity", "name is " + app.getName());
            Log.d("MainActivity", "version is " + app.getVersion());
        }
    }

這樣點選按鈕之後就會打印出資料

優化程式:

一個應用程式很可能會在許多地方都是用到網路功能,而傳送HTTP請求的程式碼基本都是相同的,我們應該將這些

通用的網路操作提取到一個公共的類裡,並提供一個靜態方法,當想要發起網路請求的時候,只需簡單呼叫一下這個

方法即可 新建一個HttpUtil工具類

先是使用HttpURLConnection來處理網路請求

package com.gougoucompany.clarence.networktest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Clarence on 2018/4/14.
 * 將通用的網路操作提取到一個公共的類裡
 */

public class HttpUtil {

    public static String sendHttpRequest(String address) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(address);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(8000);
            connection.setReadTimeout(8000);

            /*httpUrlConnection.setDoOutput(true);以後就可以使用conn.getOutputStream().write()
            httpUrlConnection.setDoInput(true);以後就可以使用conn.getInputStream().read();
            get請求用不到conn.getOutputStream(),因為引數直接追加在地址後面,因此預設是false。
            post請求(比如:檔案上傳)需要往服務區傳輸大量的資料,這些資料是放在http的body裡面的,
            因此需要在建立連線以後,往服務端寫資料. 因為總是使用conn.getInputStream()獲取服務端
            的響應,因此預設值是true。  */
            connection.setDoInput(true);
            connection.setDoOutput(true);

            InputStream in = connection.getInputStream();

            //InputStreamReader是位元組流通向字元流的橋樑:它使用指定的charset讀取位元組並將其解碼為字元
            //為了達到效率,可以在BufferedReader內包裝InputStreamReader
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            return response.toString();
        } catch(Exception e) {
            e.printStackTrace();

            //返回異常的名稱
            return e.getMessage();
        } finally {
            if(connection != null) {
                connection.disconnect();
            }
        }
    }
}
注意:

網路請求通常都是屬於耗時操作,而sendHttpRequest()方法內部並沒有開啟執行緒,這樣就可能導致在

呼叫sendHttpRequest()方法的時候使得主執行緒被阻塞住

但是在sendHttpRequest()方法中開啟一個執行緒來發起HTTP請求,那麼伺服器相應的資料是無法進行返回的,所有的

耗時邏輯都是在子執行緒裡進行的,sendHttpRequest()方法會在伺服器還沒來得及響應的時候就執行結束了,當然也就

無法返回響應的資料了。那麼我們可以使用java的回撥機制來解決這個問題

首先需要定義一個介面

* Created by Clarence on 2018/4/14.
* 我們在介面中定義了兩個方法,onFinish()方法表示當服務成功相應我們的請求的時候呼叫
* onError()表示當進行網路操作出現錯誤的時候呼叫.onFinish()方法中的引數代表著伺服器返回的
* 引數,而onError()方法中的引數記錄著錯誤的詳細資訊
package com.gougoucompany.clarence.networktest;

/**
 * Created by Clarence on 2018/4/14.
 */

public interface HttpCallbackListener {

    void onFinish(String response);

    void onError(Exception e);
}

接著修改HttpUtil中的程式碼

package com.gougoucompany.clarence.networktest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Clarence on 2018/4/14.
 * 將通用的網路操作提取到一個公共的類裡
 */

public class HttpUtil {

    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        new Thread(new Runnable(){
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL(address);
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);

            /*httpUrlConnection.setDoOutput(true);以後就可以使用conn.getOutputStream().write()
            httpUrlConnection.setDoInput(true);以後就可以使用conn.getInputStream().read();
            get請求用不到conn.getOutputStream(),因為引數直接追加在地址後面,因此預設是false。
            post請求(比如:檔案上傳)需要往服務區傳輸大量的資料,這些資料是放在http的body裡面的,
            因此需要在建立連線以後,往服務端寫資料. 因為總是使用conn.getInputStream()獲取服務端
            的響應,因此預設值是true。  */
                    connection.setDoInput(true);
                    connection.setDoOutput(true);

                    InputStream in = connection.getInputStream();

                    //InputStreamReader是位元組流通向字元流的橋樑:它使用指定的charset讀取位元組並將其解碼為字元
                    //為了達到效率,可以在BufferedReader內包裝InputStreamReader
                    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) {
                    if(listener != null) {
                        //回撥onError()方法
                        listener.onError(e);
                    }
                } finally {
                    if(connection != null) {
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
}

我們首先給sendHttpRequest()方法新增一個HttpCallbackListener引數,並在方法的內部開啟了一個子執行緒,然後在子執行緒中執行具體的網路操作。(子執行緒中是無法通過return返回資料的)這裡我們將伺服器響應的資料傳入了HttpCallbackListener的onFinish()方法中,如果出現了異常就將異常原因傳入到onError()方法中。

現在sendHttpRequest()方法接受兩個引數,我們還需將HttpCallbackListener例項傳入

HttpUtil.sendHttpRequest(address,, new HttpCallbackListener() {
	@Override
	public void onFinish(String response) {
	//在這裡根據返回內容執行具體的邏輯
	}

	@Override
	public void onError(Exception e){
	//在這裡對異常情況進行處理
	}
}

使用OkHttp來處理網路請求就非常的簡單了

我們在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);
                
    }
/*
 * Copyright (C) 2014 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package okhttp3;

import java.io.IOException;

public interface Callback {
  /**
   * Called when the request could not be executed due to cancellation, a connectivity problem or
   * timeout. Because networks can fail during an exchange, it is possible that the remote server
   * accepted the request before the failure.
   */
  void onFailure(Call call, IOException e);

  /**
   * Called when the HTTP response was successfully returned by the remote server. The callback may
   * proceed to read the response body with {@link Response#body}. The response is still live until
   * its response body is {@linkplain ResponseBody closed}. The recipient of the callback may
   * consume the response body on another thread.
   *
   * <p>Note that transport-layer success (receiving a HTTP response code, headers and body) does
   * not necessarily indicate application-layer success: {@code response} may still indicate an
   * unhappy HTTP response code like 404 or 500.
   */
  void onResponse(Call call, Response response) throws IOException;
}

可以看到okhttp3.Callback是OkHttp庫中自帶的一個回撥介面,類似於我們剛才自己編寫的HttpCallbackListener

OkHttp在equeue()方法的內部幫我們開啟好子執行緒,然後會在子執行緒中去執行HTTP請求,並將最終的結果回撥到okhttp3.Callback中

我們在呼叫sendOkHttpRequest()方法的時候可以這樣寫。

HttpUtil.sendOkHttpRequest(address, new okhttp3.Callback(){
	
	@Override
	public void onResponse(Call call, Response response) throws IOException{
	//得到伺服器返回的具體內容
	String responseData = resposne.body().toString(0;)
	}

	@Override
	public void onFailure(Call call, IOException e) {
	//在這裡對異常情況進行處理

	}
})

要注意的是不論是HttpURLConnection還是OkHttp,最終的回撥介面都是在子執行緒中執行,因此我們不可以在這裡執行

任何的UI操作,除非藉助RunOnUiThread()方法切換到主執行緒中執行。