Android HttpClient HttpUrlConnection用法總結
HttpClient
這個不用說了,Apache的API,但是不推薦使用了,在最新的api中甚至都把HttpClient去掉了。但是還是有必要掌握下HttpClient的用法的
GET方式
//先將引數放入List,再對引數進行URL編碼
List<BasicNameValuePair> params = new LinkedList<BasicNameValuePair>();
params.add(new BasicNameValuePair("param1", "中國"));
params.add(new BasicNameValuePair("param2" , "value2"));
//對引數編碼
String param = URLEncodedUtils.format(params, "UTF-8");
//baseUrl
String baseUrl = "http://ubs.free4lab.com/php/method.php";
//將URL與引數拼接
HttpGet getMethod = new HttpGet(baseUrl + "?" + param);
HttpClient httpClient = new DefaultHttpClient();
try {
HttpResponse response = httpClient.execute(getMethod); //發起GET請求
Log.i(TAG, "resCode = " + response.getStatusLine().getStatusCode()); //獲取響應碼
Log.i(TAG, "result = " + EntityUtils.toString(response.getEntity(), "utf-8"));//獲取伺服器響應內容
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
POST方法
//和GET方式一樣,先將引數放入List
params = new LinkedList<BasicNameValuePair>();
params.add(new BasicNameValuePair("param1", "Post方法"));
params.add(new BasicNameValuePair("param2", "第二個引數"));
try {
HttpPost postMethod = new HttpPost(baseUrl);
postMethod.setEntity(new UrlEncodedFormEntity(params, "utf-8")); //將引數填入POST Entity中
HttpResponse response = httpClient.execute(postMethod); //執行POST方法
Log.i(TAG, "resCode = " + response.getStatusLine().getStatusCode()); //獲取響應碼
Log.i(TAG, "result = " + EntityUtils.toString(response.getEntity(), "utf-8")); //獲取響應內容
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpClient傳遞複雜的引數,比如檔案 需要額外的jar包
常見問題
異常處理
協議異常ClientProtocolException
: 無效的cookie 很多http請求需要提供登入憑證 如果沒有則協議異常
連線超時SocketTimeoutException
: 無法連線到伺服器比如伺服器不可用 那麼就連線超時
套接字超時ConnectTimeoutException
: 既定時間內未收到伺服器響應此時可以連線到伺服器 但是未收到響應 那麼套接字超時
HttpConnectionparam.setconnectiontimeout(param,5000) //連線超時時間
HttpConnectionparam.setsotimeout(param,5000) //套接字連線超時
ConnManagerParams.settimeout(param,5000) //連線管理器的超時 定義應用程式等待多久才讓一個連線退出連線池的管理 比如連線池已經滿了 新的連線就必須要等待了
使用try catch塊來捕獲
多執行緒問題
可以設定單例的httpclient 這樣就可以共享設定的連線引數,但是單例的話 多執行緒就會有問題
HttpClient httpClient = new DefaultHttpClient(); 有多執行緒問題
比如兩個執行緒都呼叫httpClient.execute(getMethod); getMethod使用的是同一個HttpGet物件 那麼毫無疑問多執行緒問題
HttpConnectionparam.setconnectiontimeout(params,5000)
HttpConnectionparam.setsotimeout(params,5000)
ConnManagerParams.settimeout(params,5000)
HttpClient httpClient = new DefaultHttpClient(ThreadSafeClientManager conMgr,HttpParams params);
ThreadSafeClientManager
負責管理所有的httpclient的http連線 內部實現不會有多執行緒問題
此時的HttpParams作用在HttpClient上,所以可以供所有的HttpGet HttpPost對像共享
如果要定義自己的連線引數 那麼可以
HttpGet getMethod = new HttpGet(baseUrl + "?" + param);
HttpParams params= getMethod.getarams();
HttpConnectionparam.setconnectiontimeout(param,5000);
getMethod.setparams(params);
此時的HttpParams作用在HttpGet上,不會影響到HttpClient共享的連線引數
AndroidHttpClient
HttpClient子類 適用於android開發人員 連線超時/套接字超時預設20s
預設是執行緒安全的ThreadSafeClientManager
HttpUrlConnection
HttpUrlConnection屬於Java的標準類庫
更輕量了 推薦使用這個 4.4開始底層通過Okhttp來實現
HttpURLConnection的多執行緒問題? 因為採取Okhttp的底層實現,是木有多執行緒的問題的,具體是為什麼,需要研究
HttpURLConnection使用
1. HttpURLConnection連線URL
1)建立一個URL物件
URL url = new URL(http://www.baidu.com);
2)利用HttpURLConnection物件從網路中獲取網頁資料
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
3)設定連線超時
conn.setConnectTimeout(6*1000);
4)對響應碼進行判斷
if (conn.getResponseCode() != 200) //從Internet獲取網頁,傳送請求,將網頁以流的形式讀回來
throw new RuntimeException(“請求url失敗”);
5)得到網路返回的輸入流
InputStream is = conn.getInputStream();
6)String result = readData(is, “GBK”); //檔案流輸入出文件用outStream.write
7)conn.disconnect();
總結:
- 記得設定連線超時,如果網路不好,Android系統在超過預設時間會收回資源中斷操作.
- 返回的響應碼200,是成功.
- 在Android中對檔案流的操作和JAVA SE上面是一樣的.
- 在對大檔案的操作時,要將檔案寫到SDCard上面,不要直接寫到手機記憶體上.
- 操作大檔案是,要一遍從網路上讀,一遍要往SDCard上面寫,減少手機記憶體的使用.
- 對檔案流操作完,要記得及時關閉.
2. 向Internet傳送請求引數
步驟:
1)建立URL物件:URL realUrl = new URL(requestUrl);
2)通過HttpURLConnection物件,向網路地址傳送請求
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
3)設定容許輸出:conn.setDoOutput(true);
4)設定不使用快取:conn.setUseCaches(false);
5)設定使用POST的方式傳送:conn.setRequestMethod(“POST”);
6)設定維持長連線:conn.setRequestProperty(“Connection”, “Keep-Alive”);
7)設定檔案字符集:conn.setRequestProperty(“Charset”, “UTF-8”);
8)設定檔案長度:conn.setRequestProperty(“Content-Length”, String.valueOf(data.length));
9)設定檔案型別:conn.setRequestProperty(“Content-Type”,”application/x-www-form-urlencoded”);
10)以流的方式輸出.
總結:
- 傳送POST請求必須設定允許輸出
- 不要使用快取,容易出現問題.
- 在開始用HttpURLConnection物件的setRequestProperty()設定,就是生成HTML檔案頭.
3. 向Internet傳送xml資料
XML格式是通訊的標準語言,Android系統也可以通過傳送XML檔案傳輸資料.
1)將生成的XML檔案寫入到byte陣列中,並設定為UTF-8:byte[] xmlbyte = xml.toString().getBytes(“UTF-8”);
2)建立URL物件,並指定地址和引數:URL url = new URL(http://localhost:8080/itcast/contanctmanage.do?method=readxml);
3)獲得連結:HttpURLConnection conn = (HttpURLConnection) url.openConnection();
4)設定連線超時:conn.setConnectTimeout(6* 1000);
5)設定允許輸出conn.setDoOutput(true);
6)設定不使用快取:conn.setUseCaches(false);
7)設定以POST方式傳輸:conn.setRequestMethod(“POST”);
8)維持長連線:conn.setRequestProperty(“Connection”, “Keep-Alive”);
9)設定字符集:conn.setRequestProperty(“Charset”, “UTF-8”);
10)設定檔案的總長度:conn.setRequestProperty(“Content-Length”, String.valueOf(xmlbyte.length));
11)設定檔案型別:conn.setRequestProperty(“Content-Type”, “text/xml; charset=UTF-8”);
12)以檔案流的方式傳送xml資料:outStream.write(xmlbyte);
總結:
- 我們使用的是用HTML的方式傳輸檔案,這個方式只能傳輸一般在5M一下的檔案.
- 傳輸大檔案不適合用HTML的方式,傳輸大檔案我們要面向Socket程式設計.確保程式的穩定性
- 將地址和引數存到byte陣列中:byte[] data = params.toString().getBytes();
HttpClient還是HttpUrlConnection
參考 Android訪問網路,使用HttpURLConnection還是HttpClient?
在Android 2.2版本之前,HttpClient擁有較少的bug,因此使用它是最好的選擇。
而在Android 2.3版本及以後,HttpURLConnection則是最佳的選擇。它的API簡單,體積較小,因而非常適用於Android專案。壓縮和快取機制可以有效地減少網路訪問的流量,在提升速度和省電方面也起到了較大的作用。對於新的應用程式應該更加偏向於使用HttpURLConnection,因為在以後的工作當中我們也會將更多的時間放在優化HttpURLConnection上面。
其實現在嘛,兩者都不用,就用Okhttp
HttpUrlConnection現在的底層實現就是通過Okhttp
HttpURLConnection java的標準類(java.net),什麼都沒封裝,用起來太原始,不方便
HttpClient Apache開源框架,提供對HTTP協議訪問的封裝,包括http的請求頭,引數,內容體,響應等及多執行緒的應用。
HttpClient方便,但是封裝了太多,也可能導致網路請求速度變慢,靈活度不夠
HttpClient就是一個增強版的HttpURLConnection ,HttpURLConnection可以做的事情 HttpClient全部可以做;HttpURLConnection沒有提供的有些功能,HttpClient也提供了
Volley中兩者的使用
我們知道Volley中api<=9使用的是HttpClientStack,內部使用HttpClient。api>9使用的是HurlStack,內部使用HttpUrlConnection
先來看HttpClientStack,使用起來很簡單
private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) {
for (String key : headers.keySet()) {
httpRequest.setHeader(key, headers.get(key));
}
}
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders);
addHeaders(httpRequest, additionalHeaders); //快取中的頭
addHeaders(httpRequest, request.getHeaders()); //request中的設定的頭
onPrepareRequest(httpRequest);
HttpParams httpParams = httpRequest.getParams();
int timeoutMs = request.getTimeoutMs();
// TODO: Reevaluate this connection timeout based on more wide-scale
// data collection and possibly different for wifi vs. 3G.
HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);
return mClient.execute(httpRequest); //呼叫HttpClient的excute方法,執行網路請求,最後直接返回HttpResponse
}
static HttpUriRequest createHttpRequest(Request<?> request,
Map<String, String> additionalHeaders) throws AuthFailureError {
case Method.GET:
return new HttpGet(request.getUrl());
case Method.POST: {
HttpPost postRequest = new HttpPost(request.getUrl());
postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
setEntityIfNonEmptyBody(postRequest, request); //設定post請求引數
return postRequest;
........
}
default:
throw new IllegalStateException("Unknown request method.");
}
private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest,
Request<?> request) throws AuthFailureError {
byte[] body = request.getBody();
if (body != null) {
HttpEntity entity = new ByteArrayEntity(body);
httpRequest.setEntity(entity); //setEntity方法設定post請求引數
}
}
看吧,使用起來很方便簡單,都是直接封裝好了,,,下面來看HurlStack,使用起來就更負責了
@Override
public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
String url = request.getUrl();
HashMap<String, String> map = new HashMap<String, String>();
map.putAll(request.getHeaders()); //取出request設定的head
map.putAll(additionalHeaders); //取出快取中的Header,如果該request前面發起過網路請求,那麼就會快取下來,同時會把http的head也快取
........
URL parsedUrl = new URL(url);
HttpURLConnection connection = openConnection(parsedUrl, request); //初始化HttpURLConnection物件
for (String headerName : map.keySet()) {
connection.addRequestProperty(headerName, map.get(headerName)); //設定Http請求的head
}
setConnectionParametersForRequest(connection, request);
// Initialize HttpResponse with data from the HttpURLConnection.
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
int responseCode = connection.getResponseCode();
if (responseCode == -1) {
// -1 is returned by getResponseCode() if the response code could not be retrieved.
// Signal to the caller that something was wrong with the connection.
throw new IOException("Could not retrieve response code from HttpUrlConnection.");
}
StatusLine responseStatus = new BasicStatusLine(protocolVersion,
connection.getResponseCode(), connection.getResponseMessage());
BasicHttpResponse response = new BasicHttpResponse(responseStatus); //HttpResponse需要自己建立
if (hasResponseBody(request.getMethod(), responseStatus.getStatusCode())) {
response.setEntity(entityFromConnection(connection)); //呼叫HttpResponse的setEntity方法設定相應內容
}
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
if (header.getKey() != null) {
Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
response.addHeader(h); //呼叫HttpResponse的addHeader方法新增響應頭
}
}
return response;
}
private HttpURLConnection openConnection(URL url, Request<?> request) throws IOException {
HttpURLConnection connection = createConnection(url);
int timeoutMs = request.getTimeoutMs();
connection.setConnectTimeout(timeoutMs); //設定連線超時時間
connection.setReadTimeout(timeoutMs);
connection.setUseCaches(false); //不使用快取?
connection.setDoInput(true); //允許輸出
// use caller-provided custom SslSocketFactory, if any, for HTTPS
if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {
((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
}
return connection;
}
//可以看到volley支援get,post,PUT等都支援的,符合http規範
static void setConnectionParametersForRequest(HttpURLConnection connection,
Request<?> request) throws IOException, AuthFailureError {
switch (request.getMethod()) {
case Method.GET:
// Not necessary to set the request method because connection defaults to GET but
// being explicit here.
connection.setRequestMethod("GET");
break;
case Method.POST:
connection.setRequestMethod("POST");
addBodyIfExists(connection, request);
...........
}
}
private static void addBodyIfExists(HttpURLConnection connection, Request<?> request)
throws IOException, AuthFailureError {
byte[] body = request.getBody();
if (body != null) {
connection.setDoOutput(true);
connection.addRequestProperty(HEADER_CONTENT_TYPE, request.getBodyContentType()); //request的getBodyContentType()方法可以設定Content-Type請求頭
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.write(body); //把getBody()返回的byte[]陣列寫入輸入流,
out.close();
}
}
private static HttpEntity entityFromConnection(HttpURLConnection connection) {
BasicHttpEntity entity = new BasicHttpEntity();
InputStream inputStream;
try {
inputStream = connection.getInputStream();
} catch (IOException ioe) {
inputStream = connection.getErrorStream();
}
entity.setContent(inputStream); //把響應內容寫入HttpEntity
entity.setContentLength(connection.getContentLength());
entity.setContentEncoding(connection.getContentEncoding());
entity.setContentType(connection.getContentType());
return entity;
}
看到兩者的區別了吧?
HttpClient使用起來很簡單
- mClient.execute(httpRequest); 直接返回HttpResponse物件,這個物件封裝了響應內容和響應頭
- httpRequest.setHeader(key, headers.get(key)); 給請求新增頭
- HttpEntity entity = new ByteArrayEntity(request.getBody()); httpRequest.setEntity(entity); //給請求新增post引數
HttpURLConnection使用麻煩多了
HttpResponse物件需要自己建立,並手動新增響應內容和響應頭,這裡建立的是BasicHttpResponse實現了HttpResponse介面
- connection.addRequestProperty(headerName, map.get(headerName)); //設定Http請求的head
- DataOutputStream out = new DataOutputStream(connection.getOutputStream()); out.write(request.getBody()); //給請求新增post引數
- response.addHeader(h); //呼叫HttpResponse的addHeader方法新增響應頭
- response.setEntity(entityFromConnection(connection)); //呼叫HttpResponse的setEntity方法設定相應內容
相關推薦
Android HttpClient HttpUrlConnection用法總結
HttpClient 這個不用說了,Apache的API,但是不推薦使用了,在最新的api中甚至都把HttpClient去掉了。但是還是有必要掌握下HttpClient的用法的 GET方式 //先將引數放入List,再對引數進行URL編碼 List
Android屬性動畫用法總結
Android 3.0提供了屬性動畫,幾乎可以代替補間動畫。屬性動畫用法更加簡潔,功能更多強大。使用屬性動畫的兩個類是ValueAnimator和ObjectAnimator。 ValueAnaimator使用示例 ValueAnimator valueAn
Android之Adapter用法總結
1.概念 Adapter是連線後端資料和前端顯示的介面卡介面,是資料和UI(View)之間一個重要的紐帶。在常見的View(List View,Grid View)等地方都需要用到Adapter。如下圖直觀的表達了Data、Adapter、View三者
Android中Adapter用法總結
Adapter是Android中一個十分常見的類,在學習中經常見到,特地把網上一些相關的好資料收集了下,以便後期學習之用。 ---------------------------------------------------------------------------
Android之Adapter用法總結(糾錯)
Android之Adapter用法總結 1.概念 Adapter是連線後端資料和前端顯示的介面卡介面,是資料和UI(View)之間一個重要的紐帶。在常見的View(ListView,GridView)等地方都需要用到Adapter。如下圖直觀的表達了Dat
Android中Calendar類的用法總結
jsb ews 寫法 需要 key data- minute bar 來講 Calendar是Android開發中需要獲取時間時必不可少的一個工具類,通過這個類可以獲得的時間信息還是很豐富的,下面做一個總結,以後使用的時候就不用總是去翻書或者查資料了。 在獲取時間之前要先獲
Android框架之Glide4.x用法總結(4.8.0版本)
在Android開發軟體開發中,一定會涉及到圖片的顯示,如果需要從後臺獲取資料的話那麼Glide框架最合適不過了(本人常用),目前Glide框架已更新到4.8版本,4.8.0版本是沒有jar包的,所以可以直接新增它的依賴。 1、新增依賴 dependencies{ implement
Android Loader用法總結
Android提供了幾種非同步載入資料的方式,AsyncTaskLoader就是其中一種,這裡對它的用法做一個總結。 Android在3.0引入了Loader(載入器),支援在Activity或Fragment中非同步載入資料。想要在低版本上使用Loader可
android final關鍵字用法簡單總結
final: final修飾的變數為常量,只能賦值一次,賦值後不可修改。 final方法不能被子類重寫 final類不能被繼承 1、final變數 必須初始化,初始化必須在宣告時或者構造方法中直接賦值。不能通過函式賦值。 2、final方法 fin
Android自定義View的用法總結
1、通過減少View的使用來增加UI的顯示效率2、構建SDK中沒有的控制元件 原文總結了4種自定義View,分別是Composite View, Custom Composite View, Flat Custom View和Async Custom Views。示例程式
Android中padding的用法總結
padding left用法:padding-left:10px; 這個意思距離左邊補距10畫素,可跟百分比如(padding-left:10%; 距離左邊補10%的距離); padding right用法:padding-right:10px; 這個意思距離右邊補距
Android BitmapFactory用法總結
BitmapFactory的作用是:Creates Bitmap objects from various sources, including files, streams, and byte-arrays。常用方法如下: decodeByteArray(byte[]
git branch用法總結
如果 命名 參數 war blank org 2.6 重命名 scm Git branch git branch 不帶參數:列出本地已經存在的分支,並且在當前分支的前面加“*”號標記,例如: #git branch* master
numpy中一些常用函數的用法總結
num matrix 空白 記錄 維數 補充 結果 創建 array 先簡單記錄一下,後續補充詳細的例子 1. strip()函數 s.strip(rm):s為字符串,rm為要刪除的字符序列 只能刪除開頭或是結尾的字符或者字符串。不能刪除中間的字符或是字符串 當rm為空
數組去重,call、apply、bind之間的區別,this用法總結
步驟 -- 之間 undefined 定義 ply clas turn 需要 一、數組去重,直接寫到Array原型鏈上。 1 //該方法只能去除相同的數字 不會去判斷24和‘24‘是不同的 所有數字和字符串數字是相同是重復的 2 Array.prototype
JavaSE(一) IO類層次關系和各種IO流的用法總結
思想 單位 out 9.png 什麽 輸入流 謝謝 混亂 體系 今天把IO流的這一知點進行一下總結,因為在之前使用io流的時候,就只知道幾個重點常用的IO類,比如FileInputStream,BufferedInputStream(緩沖流)等等,但是不知道它處
最詳細的 Android Toolbar 開發實踐總結(轉)
activity resource listener nba flat xmlns mat https ons 轉自:http://www.codeceo.com/article/android-toolbar-develop.html 過年前發了一篇介紹 Transluc
netty用法總結
ram sed 解碼 coder fff ade med 長度 bte /**decoder和encoder,如果不需要解析,就使用系統的 * ch.pipeline().addLast(new StringDecoder()); * ch.pipeline().add
Android各種Adapter用法
app urn turn drawable key save 比較 logs display ArrayAdapter比較簡單,但它只能用於顯示文字。 1 public class MainActivity extends AppCompatActivity { 2
Android HttpLoggingInterceptor的用法簡介
nbsp -- ide evel clas 記錄 pla public andro 該攔截器用於記錄應用中的網絡請求的信息。 示例 OkHttpClient client = new OkHttpClient(); HttpLoggingInterceptor l