1. 程式人生 > >android學習二十四(網路程式設計的最佳實踐)

android學習二十四(網路程式設計的最佳實踐)

 前面的部落格已經講解了HttpURLConnection和HttpClient的用法,知道了如何發起HTTP請求,以及解析伺服器返回
 的資料。但是可能你發現了,因為一個應用程式很多地方都可能使用網路功能,而傳送HTTP請求的程式碼基本相同,如果每次我們都去編寫一遍傳送HTTP請求的程式碼,這顯然不太好。
    通常情況下我們都應該將這些通用的網路操作提取到一個公共的類裡,並提供一個靜態方法,當想要發起網路請求的時候只需簡單地呼叫一下這個方法即可。比如下面的寫法:

package com.jack.networktest;

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

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);
			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);
			}
			return response.toString();
		}catch(Exception e){
			e.printStackTrace();
			return e.getMessage();
		}finally{
			if(connection!=null){
				connection.disconnect();
			}
		}
	}
}


以後每當要發起一條HTTP請求的時候就可以這樣寫:
  String address="http://www.baidu.com";
  String response=HttpUtil.sendHttpRequest(address);

         在獲取到伺服器響應的資料後我們就可以對它進行解析和處理了。但是需要注意,網路請求通常都是屬於耗時操作,而 sendHttpRequest方法的內部並沒有開啟執行緒,這樣就可能導致在呼叫sendHttpRequest方法的時候使得主執行緒阻塞住。你可能說,在sendHttpRequest方法內部開啟一個執行緒不就解決了阻塞這個問題了嘛。其實沒那麼簡單,因為如果我們在sendHttpRequest方法中開啟了一個執行緒來發起HTTP請求,那麼伺服器響應的資料是無法進行返回的,所有的耗時邏輯都是在子執行緒裡進行的,sendHttpRequest方法會在伺服器還來得及響應的時候就執行結束了,當然也就無法返回響應的資料了。
  那麼這種情況該如何解決?其實解決方法可以使用java的回撥機制,下面就讓我們來學習一下回調機制到底如何使用的。
  首先需要定義一個介面,比如將它命名成HttpCallbackListener,程式碼如下所示:
  public interfac HttpCallbackListener{
  void onFinish(String response);
  void onError(Exception e);
  }
  可以看到,我們在介面中定義了兩個方法,onFinish(String response)方法表示當伺服器成功響應我們請求
  的時候呼叫,onError(Exception e)表示當進行網路操作出現錯誤的時候呼叫。這兩個方法都帶有引數,
  onFinish(String response)方法中的引數代表著伺服器返回的資料,而onError(Exception e)方法
  中的引數記錄著錯誤的詳細資訊。

       接著修改HttpUtil中的程式碼:

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

public class HttpUtil {

	public static void sendHttpRequest(final String address,
			final HttpCallbackListener listener){
		new Thread(new Runnable(){

			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				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){
					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(){
   public void onFinish(String response){
   //在這裡根據返回內容執行具體的邏輯
   }
   
   public void onError(Exception e){
      //在這裡對異常進行處理
   }
   
  });


這樣的話,當伺服器成功響應的時候我們就可以在onFinish方法裡對響應資料進行處理了,類似地,如果出現了異常,就可以在onError方法裡對異常情況進行處理。如此一來,我們就巧妙的利用回撥機制將響應資料成功返回給呼叫方了。
  另外需要注意的是,onFinish方法和onError方法最終還是在子執行緒中執行的,因此我們不可以在這裡執行任何的
  UI操作,如果需要根據返回的結果來更新UI,則仍然要使用非同步訊息處理機制。

相關推薦

android學習網路程式設計最佳實踐

 前面的部落格已經講解了HttpURLConnection和HttpClient的用法,知道了如何發起HTTP請求,以及解析伺服器返回  的資料。但是可能你發現了,因為一個應用程式很多地方都可能使用網路功能,而傳送HTTP請求的程式碼基本相同,如果每次我們都去編寫一遍傳

LNMP架構php-fpm的pool

二十四、php-fpm的pool     php-fpm的Pool池是支援定義多個pool的。每個pool可以監聽不同的sock、tcp/ip。那nginx有好幾個站點,每個站點可以使用一個pool。這樣做的好處是當其中的一個php502(可能是php資源不夠)了。如果所

VS2013/MFC程式設計入門之常用控制元件:組合框控制元件Combo Box

 上一節講了列表框控制元件ListBox的使用,本節主要講解組合框控制元件Combo Box。組合框同樣相當常見,例如,在Windows系統的控制面板上設定語言或位置時,有很多選項,用來進行選擇的控制元件就是組合框控制元件。        組合框控制元件簡介     

學習

linux學習六周第一次課(3月12日)9.1 正則介紹_grep上9.2 grep中9.3 grep下擴展把一個目錄下,過濾所有.php文檔中含有eval的行grep -r --include=".php" ‘eval‘ /data/正則介紹_grep上grep上-r 遍歷一遍所有子目錄

Python之路(第三篇) 網路程式設計:驗證客戶端合法性

一、驗證客戶端合法性 如果你想在分散式系統中實現一個簡單的客戶端連結認證功能,又不像SSL那麼複雜,那麼利用hmac+加鹽的方式來實現。   客戶端驗證的總的思路是將服務端隨機產生的指定位數的位元組傳送到客戶端,兩邊同時用hmac進行加密,然後對生成的密文進行比較,相同就是合法的客戶端,不相同就是不合法

、併發程式設計之簡易資料連線池

public class MyDataSource { private LinkedList<Connection> pool = new LinkedList(); //連結串列放連線池用 private static final int INIT_CONNECTION

JavaWeb學習 ()————Filter(過濾器)常見應用

一、統一全站字元編碼   通過配置引數charset指明使用何種字元編碼,以處理Html Form請求引數的中文問題 1 package me.gacl.web.filter; 2 3 import java.io.IOException;

【Katalon學習】呼叫測試用例Call Test Case

在手動檢視中呼叫測試用例 按照下面的步驟來呼叫手動檢視中的另一個測試用例: 1.在手動檢視中開啟一個測試用例,然後從命令工具欄中選擇“Call Test Case”選項。 2.測試用例瀏覽器對話方塊將顯示專案中所有現有的測試用例。選擇要呼叫的測試用例並單擊OK。 &nbs

opencv學習()之腐蝕與膨脹

腐蝕和膨脹是對二維圖片的進行操作的形態學運算,簡單來講形態學操作就是基於形狀的一系列影象處理操作,通過將結構元素作用於輸入影象來產生輸出影象。腐蝕(Erosion)和膨脹(Dilation)是最基本的形態學操作,他們運用廣泛主要有: . 消除噪聲

shell學習天----提取開頭或結尾數行

提取開頭或結尾數行 有時,會需要從文字檔案裡把幾行字----多半是靠近開頭或結尾的幾行,提取出來;或者,有時只要瞧瞧工作日誌的後面幾行,就可以瞭解最近工作活動的大概情況.可以用下面的方式顯示標準錢n條記錄,或是命令列檔案列表中的每一個前n條記錄. head -n n [fi

我與bug過日子餘年linux和python相關

1、cenos7安裝python3後pip install出現gcc failed安裝不成功(2018/9/8) 詳情:  用安裝python模組出現error: command 'gcc' failed with exit status 1 ,明明裝了g

LAMP架構 Apache配置訪問控制

十四、apache 訪問控制 在Apache2.2版本中,訪問控制是基於客戶端的主機名、IP地址以及客戶端請求中的其他特徵,使用Order(排序), Allow(允許), Deny(拒絕),Satisfy(滿足)指令來實現。 在Apache2.4版本中,使用mod_authz_host這

LNMP架構php-fpm程序管理【完】

二十七、php-fpm程序管理 1、php-fpm的程序管理有兩種模式 php-fpm的程序數也是可以根據設定分為動態和靜態的。 靜態模式:直接開啟指定數量的php-fpm程序,不再增加或者減少;動態模式:開始的時候開啟一定數量的php-fpm程序,當請求量變大的時候,動態的增加php-

LNMP架構php-fpm的open_basedir

二十六、php-fpm的open_basedir        將 PHP 所能開啟的檔案限制在指定的目錄樹,包括檔案本身。本指令不受安全模式開啟或者關閉的影響。       當一個指令碼試圖用例如 fopen() 或者

Android學習之基礎知識七—碎片的最佳實踐

一、Android碎片(Fragment)的最佳實踐——簡易版新聞應用 第一步:新建FragmentBestPractice專案,在app/build.gradle當中新增:RecyclerView 依賴庫,注意:新增完成後,一定要記住點選右上角的:Sync now 第二步:建立新聞實體類 第三

Android學習筆記——UI基礎之編寫介面最佳實踐

參考書籍:Android第一行程式碼(第二版).郭霖著 1、製作Nine-Patch圖片 一種被特殊處理過的png圖片,能夠指定那些區域可以被拉伸、哪些不可以。在Android sdk目錄下有一個tools資料夾,找到draw9patch.bat檔案來製作N

oracle sql 高階程式設計學習筆記)

子查詢因子化例項演示 1、使用子查詢因子化 2、使用INLINE提示,查詢因子做內聯處理。 3、再增加一次結果集的引用 4、增加一次結果集 使用內聯 *+inline 在oracle 官方文件中

Android開發系列:Notification的功能與使用方法

font _id when ice extends 開發 content androi mark 關於消息的提示有兩種:一種是Toast,一種就是Notification。前者維持的時間比較短暫,後者維持的時間比較長。 並且我們尋常手機的應用比方網易、貼吧等等都有非常多

Python學習筆記StringIO和BytesIO

nbsp from 寫入 enc print == world! byte 初始化 StringIO 很多時候,數據讀寫不一定是文件,也可以在內存中讀寫。 StringIO顧名思義就是在內存中讀寫str。 要把str寫入StringIO,我們需要先創建一個String

Python學習—— 前端基礎之Bookstrap

asc script nta 學習 基本 www. red hicon 分享 一、Bootstrap介紹 Bootstrap是Twitter開源的基於HTML、CSS、JavaScript的前端框架。 它是為實現快速開發Web應用程序而設計的一套前端工具包。 它支持響應式布