1. 程式人生 > >網路連線之Http及非同步操作AsyncTask

網路連線之Http及非同步操作AsyncTask

      Http個人理解為是基於請求、響應,無狀態,應用層的超文字傳輸協議。其特點有:支援客戶端與伺服器之間互動模式;簡單快捷;靈活;無連線;無狀態。

      Http介紹:HTTP是一個屬於應用層的面向物件的協議,由於其簡捷、快速的方式,適用於分散式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴充套件。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的規範化工作正在進行之中,而且HTTP-NG(Next Generation of HTTP)的建議已經提出。

      HTTP協議的主要特點可概括如下:            1.支援客戶/伺服器模式。


            2.簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯絡的型別不同。由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
            3.靈活:HTTP允許傳輸任意型別的資料物件。正在傳輸的型別由Content-Type加以標記。
            4.無連線:無連線的含義是限制每次連線只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連線。採用這種方式可以節省傳輸時間。
            5.無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的資料量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

       在使用網路連線前我們要在AndroidManifest.xml中註冊相應的許可權,將其放在application和manifest之間,也就是說和application是並列的許可權,其程式碼如下所示:

<span style="font-size:18px;"><uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</span>


         在實際連網之前要先檢查當前的網路環境是否可用,其程式碼如下所示:

<span style="font-size:18px;">ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
    //網路連線可用
} else {
    //網路連線不可用!
}
</span>


        網路操作會遇到不可預期的延遲。顯然為了避免一個不好的使用者體驗,總是在UI Thread之外去執行網路操作。AsyncTask 類提供了一種簡單的方式來處理這個問題
doInBackground()) 執行 downloadUrl()方法。Web URL作為引數,方法downloadUrl() 獲取並處理網頁返回的資料,執行完畢後,傳遞結果到onPostExecute()。引數型別為String.onPostExecute()) 獲取到返回資料並顯示到UI上。其相關程式碼如下所示:

<span style="font-size:18px;">private class DownloadWebpageText extends AsyncTask<String, Void, String> {
		@Override
		protected String doInBackground(String... urls) {

			// 引數從execute()方法傳入, params[0]表示url.
			//獲取url資源資料並返回
		}

		// onPostExecute方法中處理AsyncTask返回的結果
		@Override
		protected void onPostExecute(String result) {

		}

	}
</span>


       下面為例項的程式碼,在xml佈局中只放置了兩個Button分別用於不同的連接獲取方式和一個TextView用於顯示獲取到的內容,此處獲取到的圖片資源暫時沒有解析顯示,其具體的程式碼如下所示:

<span style="font-size:18px;">package com.sc.android.httpcoliect;
/**
 * 由於此處沒有學習圖片的解析,所以圖片的內容沒有顯示出來
 */
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.widget.Button;

import com.sc.android.R;
import com.sc.android.util.Logs;

public class HttpActivity extends Activity {
	private Button mHttpContentBtn, mHttpUrlBtn;
	private WebView mHttpWebView;//用於顯示讀取到的Url連線內容
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_http_layout);

		mHttpContentBtn = (Button) findViewById(R.id.http_client_btn);
		mHttpUrlBtn = (Button) findViewById(R.id.http_url_btn);
		mHttpWebView = (WebView) findViewById(R.id.http_webview);

		mHttpContentBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				//htmlUrl是Tomcat伺服器中自己寫的html佈局資訊
				String htmlUrl = "http://192.168.1.153:8080/html/login.html";
				new AsyncTask<String, Void, String>() {
					@Override
					protected String doInBackground(String... params) {
						String url = params[0];

						return getHttpClient(url);
					}
					protected void onPostExecute(String result) {
						if (result != null) {
							Logs.v("服務端返回的資訊是  :" + result);

							mHttpWebView.loadData(result,
									"text/html; charset=UTF-8", null);

						}
					}

				}.execute(htmlUrl);

			}
		});
		mHttpUrlBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String htmlUrl = "http://www.baidu.com";
				new AsyncTask<String, Void, String>() {

					@Override
					protected String doInBackground(String... params) {
						String url = params[0];

						return getDataByHttpUrlConnection(url);
					}

					protected void onPostExecute(String result) {
						if (result != null) {
							Logs.v("服務端返回的資訊是  :" + result);

							mHttpWebView.loadData(result,
									"text/html; charset=UTF-8", null);
						}
					}
				}.execute(htmlUrl);
			}
		});
	}
	public String getHttpClient(String httpUrl) {
		try {
			HttpClient httpClient = new DefaultHttpClient();
			HttpGet httpGet = new HttpGet(httpUrl);
			HttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			//HttpURLConnection.HTTP_OK即200響應碼
			if (statusCode == HttpURLConnection.HTTP_OK) {
				InputStream ins = response.getEntity().getContent();
				//將讀取到的資訊轉換成utf-8編碼
				BufferedReader br = new BufferedReader(new InputStreamReader(
						ins, "utf-8"));
				StringBuilder sb = new StringBuilder();
				String line = null;
				while ((line = br.readLine()) != null) {
					sb.append(line);
				}
				return sb.toString();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 從網路獲取資料通過HttpURLConnection方式實現 Get
	 */
	private String getDataByHttpUrlConnection(String url1) {
		StringBuffer sb = null;
		InputStream is = null;
		BufferedReader br = null;
		HttpURLConnection conn = null;
		OutputStream os = null;
		BufferedWriter bw = null;
		try {
			// 封裝訪問伺服器的地址
			URL url = new URL(url1);
			// 開啟對伺服器的連線
			conn = (HttpURLConnection) url.openConnection();
			// 設定輸入輸出流
			// conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestMethod("GET");
			// 連線伺服器
			conn.connect();

			/** 讀入伺服器資料的過程 **/
			// 得到輸入流
			is = conn.getInputStream();
			// 建立包裝流
			br = new BufferedReader(new InputStreamReader(is, "utf-8"));
			// 定義String型別用於儲存單行資料
			String line = null;
			// 建立StringBuffer物件用於儲存所有資料
			sb = new StringBuffer();
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.disconnect();
				if (bw != null) {
					bw.close();
				}
				if (os != null) {
					os.close();
				}
				if (br != null) {
					br.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

}
</span>


       其效果顯示如下:

    用getHttpClient方式獲取網路資源是有可能會解析出錯或解析不出來的情況。由於剛接觸,有錯的地方請見諒。