Android的HTTP請求方式
前言
大多數網絡連接的Android應用程序都將使用HTTP發送和接收數據對於Http協議的工作原理,一句話概括的話,就是客戶端向服務器發出一條HTTP請求,服務器收到之后會返回一些數據給客戶端,然后客戶端再對這些數據進行解析和處理就可以了。
一、HTTP協議的主要特點:
支持客戶/服務器模式
簡單快速:客戶向服務端請求服務時,只需傳送請求方式和路徑。
靈活:允許傳輸任意類型的數據對象。由Content-Type加以標記。
無連接:每次響應一個請求,響應完成以后就斷開連接。
無狀態:服務器不保存瀏覽器的任何信息。每次提交的請求之間沒有關聯
持續性: 瀏覽器和服務器建立TCP連接后,可以請求多個對象
非持續性: 瀏覽器和服務器建立TCP連接后,只能請求一個對象
二、一些需要注意的問題
1.POST和GET的區別
Post一般用於更新或者添加資源信息 Get一般用於查詢操作,而且應該是安全和冪等的
Post更加安全 Get會把請求的信息放到URL的后面
Post傳輸量一般無大小限制 Get不能大於2KB
Post執行效率低 Get執行效率略高
2.為什么POST效率低,Get效率高?
Get將參數拼成URL,放到header消息頭里傳遞
Post直接以鍵值對的形式放到消息體中傳遞。
但兩者的效率差距很小很小。
Android系統提供了兩種HTTP通信類,HttpURLConnection和HttpClient.兩者都支持HTTPS,流式傳輸上傳和下傳,可配置超時,IPv6和連接池
不過由於HttpClient存在的API數量過多,擴展困難等缺陷,在開發中也不會推薦使用這種方式。因此在Android M(6.0版本)系統中,HttpClient的功能被完全移除了,標志着此功能被正式棄用,所以今天就介紹一下現在官方建議使用HttpURLConnection的用法.
HttpURLConnection是適用於大多數應用程序的通用輕量級的HTTP客戶端,這個階段發展較為穩重緩慢,但是它的重點API能使我們能夠輕松地改進。
三、詳細過程
首先需要獲取到HttpURLConnection的實例,一般只需要new 出一個URL對象,並傳入目標的網絡地址,然后調用一下openConnection()方法即可,
URL url = new URL("http://blog.csdn.net/checkiming"); HttpURLConnection connection = (HttpURLConnection)url.openConnection();
在得到了HttpURLConnection的實例之后,可以設置一下HTTP請求所使用的方法。常用的兩個方法為: POST和GET .GET表示希望從服務器那里獲取到數據,而POST則表示希望提交數據給服務器。
connection.setRequestMethod("GET")
connection.setRequestMethod("POST")
接下來就可以進行一些自由的定制了,比如設置連接超時、讀取超時的毫秒數,以及服務器希望得到的一些消息頭等,這部分是可以根據自己的需求情況寫的,示例:
connection.setConnectTimeout(6000);
connection.setReadTimeout(6000);
之后再調用getInputStream()方法就可以獲取到服務器返回的輸入流了,剩下的任務就是對輸入流進行讀取,如下所示:
InputStream in = connection.getInputStream();
最后可以調用disconnect()這個方法將這個HTTP連接關閉掉,如下顯示
connection.disconnect();
即使Google在大部分Android版本推薦建議使用HttpURLConnection ,但在開源盛行的今天,我們完全可以使用一些出色的網絡通信庫來替代原生的HttpURLConnection ,而OkHttp也是最出色的一個。
Okhttp介紹
OkHttp是一個高效的Http客戶端,有如下的特點:
支持HTTP2/SPDY黑科技
socket自動選擇最好路線,並支持自動重連
擁有自動維護的socket連接池,減少握手次數
擁有隊列線程池,輕松寫並發
擁有Interceptors輕松處理請求與響應(比如透明GZIP壓縮,LOGGING)
基於Headers的緩存策略
之前也有說到,OKhttp是一個相對成熟的解決方案,在Android4.4的源碼中已經將HttpURLConnection替換成了OKhttp,所以我們更有理由去相信OKhttp的強大之處.
OkHttp 處理了很多網絡疑難雜症:會從很多常用的連接問題中自動恢復。如果您的服務器配置了多個IP地址,當第一個IP連接失敗的時候,OkHttp會自動嘗試下一個IP。OkHttp還處理了代理服務器問題和SSL握手失敗問題。
使用 OkHttp 無需重寫您程序中的網絡代碼。OkHttp實現了幾乎和java.net.HttpURLConnection一樣的API。如果你用了 Apache HttpClient,則OkHttp也提供了一個對應的okhttp-apache 模塊。
get參數
// 定義okhttp OkHttpClient okHttpClient_get = new OkHttpClient();// 02.請求體 Request request = new Request.Builder() .get()//get請求方式 .url("http://10.0.3.2:8080/WebServiceTest/servlet/ServcieTest?name=sy")//網址 .build(); Response response = okHttpClient_get.newCall(request).execute();if (response.isSuccessful()) { // 打印數據 System.out.println(response.body().string()); } else { throw new IOException("Unexpected code " + response); }
post請求參數
// 定義okhttp OkHttpClient okHttpClient_post_kv = new OkHttpClient(); // 定義請求體 // 執行okhttp RequestBody body = new FormBody.Builder() .add("name", "sy")//添加參數體 .add("age", "18") .build(); Request request = new Request.Builder() .post(body) //請求參數 .url("http://10.0.3.2:8080/WebServiceTest/servlet/ServcieTest") .build(); Response response = okHttpClient_post_kv.newCall(request).execute(); System.out.println(response.body().string());
post請求json
OkHttpClient okHttpClient_post_json = new OkHttpClient(); String json = "{\n" + " "age": "18",\n" + " "name": "sy"\n" + "}"; RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), json); Request request = new Request.Builder().post(body).url("http://10.0.3.2:8080/WebServiceTest/servlet/ServcieTest").build(); Response response = okHttpClient_post_json.newCall(request).execute(); System.out.println(response.body().string());
上傳圖片
OkHttpClient okHttpClient_upload = new OkHttpClient(); File file = new File(Environment.getExternalStorageDirectory() + "/download", "file.txt"); RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), file); Request request = new Request.Builder() .post(body) .url("http://10.0.3.2:8080/WebServiceTest/servlet/ServcieTest") .build(); Response response = okHttpClient_upload.newCall(request).execute(); System.out.println(response.body().string());
下載圖片
OkHttpClient okHttpClient_down = new OkHttpClient(); Request request = new Request.Builder().get().url("http://10.0.3.2:8080/WebServiceTest/p22.jpg").build(); okHttpClient_down.newCall(request).enqueue(MainActivity.this);
Call對象
Call call=client.newCall(request); //獲取Call對象 Response response=call.execute(); //同步執行網絡請求,不要在主線程執行 call.enqueue(new Callback()); //異步執行網絡請求 call.cancel(); //取消請求 call.isCanceled(); //查詢是否取消 call.isExecuted(); //查詢是否被執行過 ResponseBody body.contentLength(); //body的長度 String content=body.string(); //以字符串形式解碼body byte[] byteContent=body.bytes(); //以字節數組形式解碼body InputStreamReader reader=body.charStream(); //將body以字符流的形式解碼 InputStream inputStream=body.byteStream(); //將body以字節流的形式解碼