第一行代碼讀書筆記 9 -- 網(wǎng)絡(luò)技術(shù)

本篇文章主要介紹以幾下個(gè)知識(shí)點(diǎn):

  • 使用 HTTP 協(xié)議訪問網(wǎng)絡(luò):
    使用 HttpURLConnection 和 OKHttp亿扁;
  • 解析 XML 格式數(shù)據(jù):
    Pull 和 SAX 解析;
  • 解析 JSON 數(shù)據(jù):
    JSONObject 和 GSON 解析鸟廓。
圖片來源于網(wǎng)絡(luò)

9.1 使用 HTTP 協(xié)議訪問網(wǎng)絡(luò)

HTTP 協(xié)議从祝,其工作原理很簡(jiǎn)單:客戶端向服務(wù)器發(fā)出一條 HTTP 請(qǐng)求,服務(wù)器收到請(qǐng)求后會(huì)返回一些數(shù)據(jù)給客戶端引谜,然后客戶端再對(duì)這些數(shù)據(jù)進(jìn)行解析和處理牍陌。

9.1.1 使用 HttpURLConnection

下面學(xué)習(xí) HttpURLConnection 的用法,其請(qǐng)求步驟代碼如下:

   /**
     *  HttpURLConnection 發(fā)送請(qǐng)求
     */
    private void sendRequestWithHttpURLConnection() {
        // 開啟線程來發(fā)送網(wǎng)絡(luò)請(qǐng)求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try{
                    URL url = new URL("http://www.baidu.com");
                    // 1. 獲取 HttpURLConnection 實(shí)例
                    connection = (HttpURLConnection) url.openConnection();
                    // 2. 設(shè)置請(qǐng)求方法
                    connection.setRequestMethod("GET");
                    // 3. 自由定制煌张,如設(shè)置連接超時(shí)呐赡、讀取超時(shí)等
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    // 4. 獲取服務(wù)器返回的輸入流
                    InputStream in = connection.getInputStream();
                    // 下面對(duì)獲取到的輸入流進(jìn)行讀取
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine())!= null){
                        response.append(line);
                    }
                    showResponse(response.toString());// 顯示請(qǐng)求結(jié)果
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    if (reader != null){
                        try{
                            reader.close();
                        }catch (IOException e){
                            e.printStackTrace();
                        }
                    }
                    if (connection != null){
                        // 5.把 HTTP 連接關(guān)掉
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

別忘了聲明網(wǎng)絡(luò)權(quán)限:

<uses-permission android:name="android.permission.INTERNET" />

若是想要提交數(shù)據(jù)給服務(wù)器只需把請(qǐng)求方法改為 POST,并在獲取輸入流之前把要提交的數(shù)據(jù)寫出即可骏融。注意每條數(shù)據(jù)要以鍵值對(duì)的形式存在链嘀,數(shù)據(jù)與數(shù)據(jù)之間用 “&” 隔開,比如向服務(wù)器提交用戶名和密碼可寫成:

connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username=admin&password=123456");

9.1.2 使用 OKHttp

接下來學(xué)習(xí)下網(wǎng)絡(luò)請(qǐng)求開源項(xiàng)目 OKHttp档玻,其項(xiàng)目主頁地址是:https://github.com/square/okhttp

在使用 OKHttp 前怀泊,需要在項(xiàng)目中添加 OKHttp 庫的依賴,如下:

compile 'com.squareup.okhttp3:okhttp:3.5.0'

下面學(xué)習(xí) OKHttp 請(qǐng)求步驟误趴,如下:

   /**
     *  OKHttp 發(fā)送請(qǐng)求
     */
    private void sendRequestWithOKHttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    // 1. 創(chuàng)建 OkHttpClient 實(shí)例
                    OkHttpClient client = new OkHttpClient();
                    // 2. 創(chuàng)建 Request 對(duì)象
                    Request request = new Request.Builder().url("http://www.baidu.com").build();
                    // 3. 調(diào)用 OkHttpClient 的 newCall() 方法來創(chuàng)建 Call 對(duì)象
                    Response response = client.newCall(request).execute();
                    // 4. 獲取返回的內(nèi)容
                    String responseData = response.body().string();
                    showResponse(responseData);// 顯示請(qǐng)求結(jié)果
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

相比 HttpURLConnection霹琼,OKHttp 簡(jiǎn)單易用,若是發(fā)起一條 POST 請(qǐng)求凉当,會(huì)比 GET 請(qǐng)求稍微復(fù)雜點(diǎn)枣申,需要構(gòu)建一個(gè) RequestBody 對(duì)象來存放待提交的參數(shù):

RequestBody requestBody = new FormBody.Builder()
        .add("username","admin")
        .add("password","123456")
        .build();

然后在 Request.Builder 中調(diào)用一下 post() 方法,并將 RequestBody 對(duì)象傳入:

Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .post(RequestBody)
        .build();

9.1.3 網(wǎng)絡(luò)編程的最佳實(shí)踐

在實(shí)際開發(fā)中看杭,我們通常將這些通用的網(wǎng)絡(luò)操作提取到一個(gè)公共類里忠藤,接下來就簡(jiǎn)單封裝下網(wǎng)絡(luò)操作。

首先針對(duì) HttpURLConnection 定義一個(gè)回調(diào)接口:

public interface HttpCallbackListener {
    void onFinish(String response);// 請(qǐng)求成功時(shí)調(diào)用
    void onError(Exception e);// 請(qǐng)求失敗時(shí)調(diào)用
}

接著編寫工具類 HttpUtil:

public class HttpUtil {

    /**
     * 用 HttpURLConnection 發(fā)送請(qǐng)求
     * @param address
     * @param listener
     */
    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);
                    // 1. 獲取 HttpURLConnection 實(shí)例
                    connection = (HttpURLConnection) url.openConnection();
                    // 2. 設(shè)置請(qǐng)求方法
                    connection.setRequestMethod("GET");
                    // 3. 自由定制楼雹,如設(shè)置連接超時(shí)模孩、讀取超時(shí)等
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    connection.setDoInput(true);
                    connection.setDoOutput(true);
                    // 4. 獲取服務(wù)器返回的輸入流
                    InputStream in = connection.getInputStream();
                    // 下面對(duì)獲取到的輸入流進(jìn)行讀取
                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine())!= null){
                        response.append(line);
                    }
                    if (listener != null){
                        // 回調(diào) onFinish() 方法
                        listener.onFinish(response.toString());
                    }
                }catch (Exception e){
                    if (listener != null){
                        // 回調(diào) onError() 方法
                        listener.onError(e);
                    }
                }finally {
                    if (connection != null){
                        // 5.把 HTTP 連接關(guān)掉
                        connection.disconnect();
                    }
                }
                
            }
        }).start();
    }

    /**
     * 用 OKHttp 發(fā)送請(qǐng)求
     * @param address
     * @param callback
     */
    public static void sendOKHttpRequest(String address, Callback callback){
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        client.newCall(request).enqueue(callback);
    }
}

這時(shí)候用 HttpURLConnection 發(fā)送請(qǐng)求就可以寫成:

        HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                // 在這里根據(jù)返回內(nèi)容執(zhí)行具體的邏輯
            }

            @Override
            public void onError(Exception e) {
                // 在這里對(duì)異常情況進(jìn)行處理
            }
        });

用 OKHttp 發(fā)送請(qǐng)求就可以寫成:

       HttpUtil.sendOKHttpRequest("http://www.baidu.com", new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                 // 在這里對(duì)異常情況進(jìn)行處理
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 得到服務(wù)器返回的具體內(nèi)容
                String responseData = response.body().string();
               }
        });

另外需要注意的是尖阔,不管是使用 HttpURLConnection 還是 OKHttp,最終回調(diào)接口都還是在子線程中運(yùn)行的榨咐。

下面舉個(gè)例子鞏固下介却,在布局中放置 Button 用于發(fā)送 HTTP 請(qǐng)求,放置一個(gè) TextView 用于顯示服務(wù)器返回的數(shù)據(jù)块茁,主要代碼如下:

public class HttpActivity extends AppCompatActivity implements View.OnClickListener {

    private Button send_url_request,send_okHttp_request,clear_content;
    private TextView response_text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_http);

        response_text = (TextView) findViewById(R.id.response_text);

        send_url_request = (Button) findViewById(R.id.send_url_request);
        send_okHttp_request = (Button) findViewById(R.id.send_okHttp_request);
        clear_content = (Button) findViewById(R.id.clear_content);
        send_url_request.setOnClickListener(this);
        send_okHttp_request.setOnClickListener(this);
        clear_content.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.send_url_request:
                sendRequestWithHttpURLConnection();

            case R.id.send_okHttp_request:
                sendRequestWithOKHttp();

            case R.id.clear_content:
                showResponse(""); //清空數(shù)據(jù)
        }
    }

    /**
     *  OKHttp 發(fā)送請(qǐng)求
     */
    private void sendRequestWithOKHttp() {
        HttpUtil.sendOKHttpRequest("http://www.baidu.com", new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                 // 在這里對(duì)異常情況進(jìn)行處理
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 得到服務(wù)器返回的具體內(nèi)容
                String responseData = response.body().string();
                showResponse(responseData);
            }
        });
    }

    /**
     *  HttpURLConnection 發(fā)送請(qǐng)求
     */
    private void sendRequestWithHttpURLConnection() {
        HttpUtil.sendHttpRequest("http://www.baidu.com", new HttpCallbackListener() {
            @Override
            public void onFinish(String response) {
                // 在這里根據(jù)返回內(nèi)容執(zhí)行具體的邏輯
                showResponse(response);
            }

            @Override
            public void onError(Exception e) {
                // 在這里對(duì)異常情況進(jìn)行處理
            }
        });
    }

    /**
     * 顯示請(qǐng)求結(jié)果
     * @param response
     */
    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 在這里進(jìn)行UI 操作齿坷,將結(jié)果顯示到界面上
                response_text.setText(response);
            }
        });
    }
}

運(yùn)行效果如下:

兩種網(wǎng)絡(luò)請(qǐng)求效果

9.2 解析 XML 格式數(shù)據(jù)

在網(wǎng)絡(luò)上傳輸數(shù)據(jù)時(shí)最常用的格式有兩種:XML 和 JSON。本節(jié)來學(xué)習(xí)下如何解析 XML 格式的數(shù)據(jù)龟劲。

解析 XML 格式的數(shù)據(jù)有多種方式胃夏,這里主要介紹 Pull 解析和 SAX 解析。解析前先來看看等下要解析的 XML 文本:

xml 格式的內(nèi)容

9.2.1 Pull 解析方式

Pull 解析整個(gè)過程比較簡(jiǎn)單昌跌,具體看代碼注釋:

   /**
     * pull 解析
     * @param xmlData 要解析的xml數(shù)據(jù)
     */
    private void parseXMLWithPull(String xmlData) {
        try {
            // 1. 獲取 XmlPullParserFactory 實(shí)例
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            // 2. 借助 XmlPullParserFactory 實(shí)例得到 XmlPullParser 對(duì)象
            XmlPullParser xmlPullParser = factory.newPullParser();
            // 3. 調(diào)用 setInput() 方法設(shè)置xml數(shù)據(jù)
            xmlPullParser.setInput(new StringReader(xmlData));
            // 4. 獲取當(dāng)前的解析事件
            int eventType = xmlPullParser.getEventType();
            String id = "";
            String name = "";
            String sex = "";
            // 5. 通過 while 循環(huán)不斷地進(jìn)行解析
            while (eventType != XmlPullParser.END_DOCUMENT){
                String nodeName = xmlPullParser.getName();
                switch (eventType){
                    // 開始解析某個(gè)節(jié)點(diǎn)
                    case XmlPullParser.START_TAG:
                        if ("id".equals(nodeName)){
                            id = xmlPullParser.nextText();
                        }else if ("name".equals(nodeName)){
                            name = xmlPullParser.nextText();
                        }else if ("sex".equals(nodeName)){
                            sex = xmlPullParser.nextText();
                        }
                        break;

                    // 完成解析某個(gè)節(jié)點(diǎn)
                    case  XmlPullParser.END_TAG:
                        if ("student".equals(nodeName)){
                            Log.d("pull解析:", "id is" + id);
                            Log.d("pull解析:", "name is" + name);
                            Log.d("pull解析:", "sex is" + sex);
                        }
                        break;

                    default:
                        break;
                }
                // 獲取下一個(gè)解析事件
                eventType = xmlPullParser.next();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

9.2.2 SAX 解析方式

SAX 解析的用法比 Pull 解析要復(fù)雜些仰禀,但在語義方面會(huì)更加清楚。

用 SAX 解析需要建一個(gè)類繼承 DefaultHandler蚕愤,并重寫父類的5個(gè)方法答恶。為實(shí)現(xiàn)上面同樣的功能,新建一個(gè) ContentHandler 類萍诱,如下所示:

public class ContentHandler extends DefaultHandler {

    private String nodeName;
    private StringBuilder id;
    private StringBuilder name;
    private StringBuilder sex;

    /**
     * 開始 XML 解析時(shí)調(diào)用
     * @throws SAXException
     */
    @Override
    public void startDocument() throws SAXException {
        id = new StringBuilder();
        name = new StringBuilder();
        sex = new StringBuilder();
    }

    /**
     * 開始解析某個(gè)節(jié)點(diǎn)時(shí)調(diào)用
     * @param uri
     * @param localName
     * @param qName
     * @param attributes
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // 記錄當(dāng)前節(jié)點(diǎn)名
        nodeName = localName;
    }

    /**
     * 獲取節(jié)點(diǎn)中的內(nèi)容時(shí)調(diào)用
     * @param ch
     * @param start
     * @param length
     * @throws SAXException
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // 根據(jù)當(dāng)前節(jié)點(diǎn)名判斷將內(nèi)容添加到哪一個(gè) StringBuilder 對(duì)象中
        if ("id".equals(nodeName)){
            id.append(ch,start,length);
        }else if ("name".equals(nodeName)){
            name.append(ch,start,length);
        }else if ("sex".equals(nodeName)){
            sex.append(ch,start,length);
        }
    }

    /**
     * 完成解析某個(gè)節(jié)點(diǎn)時(shí)調(diào)用
     * @param uri
     * @param localName
     * @param qName
     * @throws SAXException
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if ("student".equals(localName)){
            Log.d("sax解析:", "id is" + id.toString().trim());
            Log.d("sax解析:", "name is" + name.toString().trim());
            Log.d("sax解析:", "sex is" + sex.toString().trim());
            // 最后要將 StringBuilder 清空掉
            id.setLength(0);
            name.setLength(0);
            sex.setLength(0);
        }
    }


    /**
     * 完成整個(gè) XML 解析時(shí)調(diào)用
     * @throws SAXException
     */
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }
}

接下來就非常簡(jiǎn)單了悬嗓,代碼如下:

   /**
     * sax 解析
     * @param xmlData
     */
    private void parseXMLWithSAX(String xmlData){
        try {
            // 創(chuàng)建 SAXParserFactory 對(duì)象
            SAXParserFactory factory = SAXParserFactory.newInstance();
            // 獲取 XMLReader 對(duì)象
            XMLReader xmlReader = factory.newSAXParser().getXMLReader();
            ContentHandler handler = new ContentHandler();
            // 將 ContentHandler 的實(shí)例設(shè)置到 XMLReader 中
            xmlReader.setContentHandler(handler);
            // 開始執(zhí)行解析
            xmlReader.parse(new InputSource(new StringReader(xmlData)));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

9.2.3 舉個(gè)例子實(shí)在點(diǎn)

下面在布局中放置兩個(gè)按鈕,分別進(jìn)行pull解析和sax解析:

public class ParseXMLActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_pull,btn_sax;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parse_xml);

        btn_pull = (Button) findViewById(R.id.btn_pull);
        btn_sax = (Button) findViewById(R.id.btn_sax);

        btn_pull.setOnClickListener(this);
        btn_sax.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_pull:
                HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.xml", new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        //ToastUtils.showShort("請(qǐng)求失敗");
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String responseData = response.body().string();
                        parseXMLWithPull(responseData);  // pull 解析
                    }
                });
                break;

            case R.id.btn_sax:
                HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.xml", new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        //ToastUtils.showShort("請(qǐng)求失敗");
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String responseData = response.body().string();
                        parseXMLWithSAX(responseData);  // sax 解析
                    }
                });
                break;
        }
    }

    /**
     * pull 解析
     * @param xmlData 要解析的xml數(shù)據(jù)
     */
    private void parseXMLWithPull(String xmlData) {  . . .  }

    /**
     * sax 解析
     * @param xmlData
     */
    private void parseXMLWithSAX(String xmlData){  . . .  }
}

運(yùn)行程序裕坊,打印的日志分別如下:

pull 解析
sax 解析

??可以看到包竹,已經(jīng)將 XML 數(shù)據(jù)成功解析出來了。

9.3 解析 JSON 數(shù)據(jù)

??類似的籍凝,解析 JSON 格式的數(shù)據(jù)有多種方式周瞎,這里主要介紹官方提供的 JSONObject 和谷歌的開源庫 GSON 來解析。解析前先來看看等下要解析的 JSON 文本:

json 格式的內(nèi)容

9.3.1 使用 JSONObject

??使用 JSONObject 解析上面內(nèi)容比較簡(jiǎn)單饵蒂,具體看代碼:

   /**
     * 用 JSONObject 解析
     * @param jsonData 需要解析的數(shù)據(jù)
     */
    private void parseJSONWithJSONObject(String jsonData) {
        try {
            // 把需要解析的數(shù)據(jù)傳入到 JSONArray 對(duì)象中
            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 sex = jsonObject.getString("sex");
                Log.d("JSONObject解析", "id is "+id);
                Log.d("JSONObject解析", "name is "+name);
                Log.d("JSONObject解析", "sex is "+sex);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

9.3.2 使用 GSON

??接下來學(xué)習(xí)下開源庫 GSON声诸,其項(xiàng)目主頁地址是:https://github.com/google/gson

??在使用 GSON 前,需要在項(xiàng)目中添加 GSON 庫的依賴退盯,如下:

compile 'com.google.code.gson:gson:2.8.0'

??GSON 可以將一段 JSON 格式的字符串自動(dòng)映射成一個(gè)對(duì)象彼乌,從而不需要手動(dòng)去編寫代碼進(jìn)行解析了。

??比如解析一段 JSON 格式數(shù)據(jù):

{"name":"Tom","age":20}

??就可以定義一個(gè) Person 類渊迁,并加入 name 和 age 兩字段慰照,然后只需調(diào)用如下代碼就可以將 JSON 數(shù)據(jù)自動(dòng)解析成一個(gè) Person 對(duì)象:

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

??若解析一段 JSON 數(shù)組會(huì)麻煩些,需要借助 TypeToken 把期望解析成的數(shù)據(jù)類型傳入到 fromJson() 方法中:

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

??GSON 的基本用法就是這樣琉朽。下面來解析上面的 JSON 文本毒租,首先新增一個(gè) Student 類:

public class Student {
    
    private String id;
    private String name;
    private String sex;

    // Getter and Setter
    . . .
}

??接下來就非常簡(jiǎn)單了,代碼如下:

   /**
     *  用 GSON 解析
     * @param jsonData
     */
    private void parseJSONWithGSON(String jsonData){
        Gson gson = new Gson();
        List<Student>studentList = gson.fromJson(jsonData,new TypeToken<List<Student>>(){}.getType());
        for (Student student:studentList){
            Log.d("GSON解析", "id is "+student.getId());
            Log.d("GSON解析", "name is "+student.getName());
            Log.d("GSON解析", "sex is "+student.getSex());
        }
    }

9.3.3 舉個(gè)例子實(shí)在點(diǎn)

??下面在布局中放置兩個(gè)按鈕漓骚,分別用 JSONObject 和 GSON 進(jìn)行 json 解析:

public class ParseJSONActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_object,btn_gson;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parse_json);

        btn_object = (Button) findViewById(R.id.btn_object);
        btn_gson = (Button) findViewById(R.id.btn_gson);

        btn_object.setOnClickListener(this);
        btn_gson.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_object:
                HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.json", new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {}

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                          String responseData = response.body().string();
                        parseJSONWithJSONObject(responseData);   // 用 JSONObject 解析
                    }
                });
                break;

            case R.id.btn_gson:
                HttpUtil.sendOKHttpRequest("http://10.0.2.2/get_data.json", new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {}

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String responseData = response.body().string();
                        parseJSONWithGSON(responseData);  // 用 GSON 解析
                    }
                });
                break;
        }

    }

    /**
     * 用 JSONObject 解析
     * @param jsonData 需要解析的數(shù)據(jù)
     */
    private void parseJSONWithJSONObject(String jsonData) { . . . }

    /**
     *  用 GSON 解析
     * @param jsonData
     */
    private void parseJSONWithGSON(String jsonData){ . . . }
}

??運(yùn)行程序蝌衔,打印的日志分別如下:

JSONObject 解析
GSON 解析

??關(guān)于網(wǎng)絡(luò)編程先學(xué)習(xí)到這,下篇文章將進(jìn)入安卓四大組件之服務(wù)的學(xué)習(xí)蝌蹂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末噩斟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子孤个,更是在濱河造成了極大的恐慌剃允,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件齐鲤,死亡現(xiàn)場(chǎng)離奇詭異斥废,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)给郊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門牡肉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淆九,你說我怎么就攤上這事统锤。” “怎么了炭庙?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵饲窿,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我焕蹄,道長(zhǎng)逾雄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任腻脏,我火速辦了婚禮鸦泳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘迹卢。我一直安慰自己辽故,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布腐碱。 她就那樣靜靜地躺著誊垢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪症见。 梳的紋絲不亂的頭發(fā)上喂走,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音谋作,去河邊找鬼芋肠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遵蚜,可吹牛的內(nèi)容都是我干的帖池。 我是一名探鬼主播奈惑,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼睡汹!你這毒婦竟也來了肴甸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤囚巴,失蹤者是張志新(化名)和其女友劉穎原在,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彤叉,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡庶柿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秽浇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片浮庐。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖兼呵,靈堂內(nèi)的尸體忽然破棺而出兔辅,到底是詐尸還是另有隱情,我是刑警寧澤击喂,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布维苔,位于F島的核電站,受9級(jí)特大地震影響懂昂,放射性物質(zhì)發(fā)生泄漏介时。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一凌彬、第九天 我趴在偏房一處隱蔽的房頂上張望沸柔。 院中可真熱鬧,春花似錦铲敛、人聲如沸褐澎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽工三。三九已至,卻和暖如春先鱼,著一層夾襖步出監(jiān)牢的瞬間俭正,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工焙畔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掸读,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像儿惫,于是被迫代替她去往敵國(guó)和親澡罚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容