主角為 HttpClient 與 HttpGet, HttpClient 是高貴的物件,整個 App 共用同一個 HttpClient,每一次存取網路建立一個新的 HttpGet 而不是建立新的 HttpClient(要包成 Singleton)。

 

不可以在 Activity 的 Main Thread 裡直接呼叫網路存取,因為很有可能出現五秒鐘的 ANR。

 

另外要在 AndroidManifest.xml 開啟網路許可權 android.permission.INTERNET。

 

記得測試的時候,若要連到本機,不可以用 localhost 或者 127.0.0.1,因為這時的本機指的是手機或 Emulator,不是開發的電腦。

 

網路連線的 Exception 可以分成三類:

 

◾傳輸:網路不通或者不穩。
◾通訊協定:許可權相關。
◾Timeout:包括 Connection timeout 與 Socket timeout,分別是 request timeout 與 response timeout。

 

對應的處理方法:

 

◾HttpClient 負責偵測並重試。
◾開發時就會發現。
◾唯一要處理的,使用重試機制。





SingleHttpClient

 

public class SingleHttpClient {

 

private static final String TAG = "SingleHttpClient";
private static HttpClient HTTPClient;

 

private SingleHttpClient() {
// singleton
}

 

public static synchronized HttpClient get() {
if (HTTPClient == null) {
Log.i(TAG, "建立 Singleton HttpClient...");
HttpParams params = new BasicHttpParams();
// 取得 connection
ConnManagerParams.setTimeout(params, 1000);
// request timeout
HttpConnectionParams.setConnectionTimeout(params, 5000);
// response timeout
HttpConnectionParams.setSoTimeout(params, 10000);
SchemeRegistry schreg = new SchemeRegistry();
schreg.register(new Scheme("HTTP",
PlainSocketFactory.getSocketFactory(), 80));
schreg.register(new Scheme("HTTPs",
SSLSocketFactory.getSocketFactory(), 443));
// 因為 HttpClient 是 Singleton,所以使用特別的 ConnectionManager
ClientConnectionManager ccMgr = new ThreadSafeClientConnManager(
params, schreg);
HTTPClient = new DefaultHttpClient(ccMgr, params);
}
return HTTPClient;
}
}

 

HttpGetActivity

 

public class HttpGetActivity extends Activity {

 

private static final String TAG = "HttpGetActivity";

 

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

 

try {
String response = this.doGetWithRetry();
}
catch (Exception e) {
Log.e(TAG, "不幸的事發生了");
}
}

 

/**
* 實做重試機制
* @return
* @throws Exception
*/
private String doGetWithRetry() throws Exception {
int retry = 3;
int current = 0;
while (current < retry) {
current++;
try {
return this.doGet();
}
catch (IOException e) {
Log.e(TAG, current + ".網路發生錯誤 - " + e.getMessage());
if (current >= retry) {
Log.e(TAG, "重試失敗");
throw e;
}
}
catch (Exception e) {
Log.e(TAG, current + ".發生未知的錯誤 - " + e.getMessage());
if (current >= retry) {
Log.e(TAG, "重試失敗");
throw e;
}
}
}
return null;
}

 

/**
* 網路讀取
* @return
* @throws IOException
*/
private String doGet() throws IOException {
BufferedReader in = null;
try {
// 使用 Singleton 且 ThreadSafe 的 HttpClient
HttpClient client = SingleHttpClient.get();
HttpGet request = new HttpGet("HTTP://cw1057.blogspot.com/");
// 網址有參數的作法
// request = new HttpGet("HTTP://cw1057.blogspot.com/search?updated-max=2011-12-11T16:33:00%2B08:00&max-results=5");

 

// 可以透過 HttpGet 來覆蓋 HttpClient 的設定,不會因為使用 Singleton 的 HttpClient 而受限
HttpParams params = request.getParams();
// 取得 connection
ConnManagerParams.setTimeout(params, 1000);
// request timeout
HttpConnectionParams.setConnectionTimeout(params, 5000);
// response timeout
HttpConnectionParams.setSoTimeout(params, 10000);

 

// 原始的方法:逐行讀取資料
// HttpResponse response = client.execute(request);
// in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
// StringBuilder html = new StringBuilder();
// String line;
// while ((line = in.readLine()) != null) {
// html.append(line + "\n");
// }
// in.close();
// String responseText = html.toString();

 

// 快速的方法:將 response 打包成 String
String responseText = client.execute(request,
new BasicResponseHandler());
Log.d(TAG,
"取得 HTML(" + responseText.length() + ") - "
+ TextUtils.substring(responseText, 0, 10)
+ " ... ");
return responseText;
}
// 不處理 Execption,交由重試機制負責
finally {
if (in != null) {
try {
in.close();
}
catch (IOException e) {
}
}
}
}
}

網路沒有開的情況:



正常的狀況,第二次再進來就沒有建立 HttpClient:
 
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()