android網(wǎng)絡(luò)框架之OKhttp
一個(gè)處理網(wǎng)絡(luò)請(qǐng)求的開源項(xiàng)目,是安卓端最火熱的輕量級(jí)框架,由移動(dòng)支付Square公司貢獻(xiàn)
HTTP是現(xiàn)代應(yīng)用程序網(wǎng)絡(luò)的方式。這是我們交換數(shù)據(jù)和媒體的方式邓萨。高效地執(zhí)行HTTP可以使您的工作負(fù)載更快现拒,并節(jié)省帶寬多律。
OkHttp是一個(gè)默認(rèn)高效的HTTP客戶端:
HTTP/2支持允許對(duì)同一主機(jī)的所有請(qǐng)求共享一個(gè)套接字肛根。
連接池減少了請(qǐng)求延遲(如果HTTP/2不可用)用爪。
透明GZIP壓縮下載大小粉渠。
響應(yīng)緩存完全避免了網(wǎng)絡(luò)重復(fù)請(qǐng)求分冈。
當(dāng)網(wǎng)絡(luò)出現(xiàn)問題時(shí),OkHttp會(huì)堅(jiān)持下去:它會(huì)從常見的連接問題中悄悄地恢復(fù)霸株。如果您的服務(wù)有多個(gè)IP地址雕沉,如果第一個(gè)連接失敗,OkHttp將嘗試替代地址去件。這對(duì)于IPv4+IPv6和托管在冗余數(shù)據(jù)中心中的服務(wù)是必要的坡椒。OkHttp支持現(xiàn)代TLS特性(TLS 1.3扰路、ALPN、證書固定)倔叼『钩可以將其配置為后退以實(shí)現(xiàn)廣泛的連接。
使用OkHttp很容易丈攒。它的請(qǐng)求/響應(yīng)API設(shè)計(jì)為流暢的構(gòu)建器和不變性渡嚣。它同時(shí)支持同步阻塞調(diào)用和帶回調(diào)的異步調(diào)用。
http協(xié)議:
HTTP肥印,超文本傳輸協(xié)議识椰,英文全稱是Hypertext Transfer Protocol,它是互聯(lián)網(wǎng)上應(yīng)用最為廣泛的一種網(wǎng)絡(luò)協(xié)議深碱。HTTP是一種應(yīng)用層協(xié)議腹鹉,它是基于TCP協(xié)議之上的請(qǐng)求/響應(yīng)式的協(xié)議,即一個(gè)客戶端與服務(wù)器建立連接后敷硅,向服務(wù)器發(fā)送一個(gè)請(qǐng)求功咒;服務(wù)器接到請(qǐng)求后,給予相應(yīng)的響應(yīng)信息绞蹦。
請(qǐng)求協(xié)議和響應(yīng)協(xié)議
請(qǐng)求協(xié)議:
①請(qǐng)求首行:
②請(qǐng)求頭信息:客戶端告訴服務(wù)器我這邊的信息
③空行
④請(qǐng)求體:get請(qǐng)求是沒有請(qǐng)求體的
響應(yīng)協(xié)議:
①響應(yīng)首行:HTTP/1.1 200 OK
②響應(yīng)頭信息:Content-Length 服務(wù)器返回?cái)?shù)據(jù)的總大小
③空行
④響應(yīng)體:服務(wù)器返回的數(shù)據(jù)
okhttp-Get請(qǐng)求
//網(wǎng)絡(luò)請(qǐng)求json串
public void getjson(){
//TODO 1:client
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.callTimeout(5, TimeUnit.SECONDS);//連接超時(shí)
builder.readTimeout(5,TimeUnit.SECONDS);//讀取超時(shí)
OkHttpClient client = builder.build();
//TODO 2:request對(duì)象
Request.Builder builder1 = new Request.Builder();
builder1.url("http://www.qubaobei.com/ios/cf/dish_list.php?stage_id=1&limit=20&");//設(shè)置網(wǎng)址
builder1.get();//設(shè)置請(qǐng)求方法
Request request = builder1.build();
//TODO 3:發(fā)起連接call
Call call = client.newCall(request);
//TODO 4:通過call得到response
call.enqueue(new Callback() {
//請(qǐng)求失敗
@Override
public void onFailure(Call call, IOException e) {
}
//請(qǐng)求成功
@Override
public void onResponse(Call call, Response response) throws IOException {
//獲得響應(yīng)體:json串
ResponseBody body = response.body();
//通過body直接轉(zhuǎn)成字符串
String json = body.string();
// Toast.makeText(MainActivity.this, ""+json, Toast.LENGTH_SHORT).show();
Message obtain = Message.obtain();
obtain.what=GET_JSON_OK;
obtain.obj=json;
handler.sendMessage(obtain);
}
});
}
okhttp-Post請(qǐng)求
//post請(qǐng)求完成注冊(cè)
private void zhuce() {
OkHttpClient client = new OkHttpClient.Builder()
.callTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
//請(qǐng)求體:phone=13594347817&passwd=123654
FormBody formBody = new FormBody.Builder()
.add("phone", "13594343356")
.add("passwd", "123654")
.build();
final Request request = new Request.Builder()
.url("https://www.apiopen.top/createUser?key=00d91e8e0cca2b76f515926a36db68f5&")
.post(formBody)//post提交必須要設(shè)置請(qǐng)求體
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String string = response.body().string();
Message obtain = Message.obtain();
obtain.what=GET_JSON_OK;
obtain.obj=string;
handler.sendMessage(obtain);
}
});
}
okhttp-download
//下載文件到SD卡中
private void sd() {
//TODO 1:client
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.callTimeout(5, TimeUnit.SECONDS)
.build();
//TODO 2:request
Request request = new Request.Builder()
.get()
.url("http://169.254.113.244/hfs/a.jpg")
.build();
//TODO 3:call
Call call = client.newCall(request);
//TODO 4:response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {//失敗
}
@Override
public void onResponse(Call call, Response response) throws IOException {//成功
ResponseBody body = response.body();
long l = body.contentLength();//獲得總大小
InputStream inputStream = body.byteStream();//響應(yīng)體-->輸入流
//邊讀邊寫
}
});
}
okhttp-upload
private void upload() throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.callTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
//上傳文件的請(qǐng)求體
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "music.mp3",//music.mp3 服務(wù)器端的名字
RequestBody.create(MediaType.parse("media/mp3"), new File("/sdcard/李伯伯.mp3")))
.build();
final Request request = new Request.Builder()
.url("http://<--ip地址-->/hfs")
.post(requestBody)//post提交必須要設(shè)置請(qǐng)求體
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
okhttp封裝
1.接口回調(diào)
public interface MyOkListener {
void onError(String mesage);//返回錯(cuò)誤信息
void onSuccess(String json);//返回?cái)?shù)據(jù)
}
public interface MyFileListener {
void setMax(int max);//設(shè)置最大值
void setProgress(int progress);//設(shè)置當(dāng)前進(jìn)度
void onFinish();//下載完成
void onError(String message);//錯(cuò)誤
}
2.定義管理類
/**
* 原則:代碼復(fù)用性+只有一個(gè)Client對(duì)象
*
*
* */
public class OkhttpUtils {
private OkHttpClient okHttpClient;//在構(gòu)造方法里面創(chuàng)建
//單例模式:構(gòu)造私有化
private OkhttpUtils(){//只會(huì)創(chuàng)建一次
//log攔截器
HttpLoggingInterceptor httpLoggingInterceptor=new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//token攔截器
Interceptor tokenInterceptor=new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request1=chain.request().newBuilder().header("token","zxc").build();
return chain.proceed(request1);
}
};
okHttpClient=new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.connectTimeout(5, TimeUnit.SECONDS)
.addInterceptor(tokenInterceptor)//添加token攔截器力奋,一定要在log攔截器之前設(shè)置
.addInterceptor(httpLoggingInterceptor)//添加log攔截器
.build();
};
//自行實(shí)例化
private static OkhttpUtils okhttpUtils=null;
//公開方法
public static OkhttpUtils getInstance(){
//雙重校驗(yàn)鎖:
if(okhttpUtils==null){
synchronized (StringBuilder.class){
if(okhttpUtils==null){
okhttpUtils=new OkhttpUtils();
}
}
}
return okhttpUtils;
}
/***
* @param str_url 網(wǎng)址
* @param listener 回調(diào) 將請(qǐng)求的結(jié)果返回給Activitt
*/
public void doget(String str_url, final MyOkListener listener){
//TODO 2:request對(duì)象
Request request=new Request.Builder().url(str_url).get().header("Connection","Keep-Alive").build();
//TODO 3:call
Call call = okHttpClient.newCall(request);
//TODO 4:加入隊(duì)列 得到response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onError(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
listener.onSuccess(response.body().string());
}
});
}
/***
*
* @param str_url 請(qǐng)求網(wǎng)址
* @param listener 回調(diào)的監(jiān)聽
* @param map 請(qǐng)求體參數(shù)
*/
public void dopost(String str_url, HashMap<String,String> map, final MyOkListener listener){
//TODO 請(qǐng)求體
FormBody.Builder builder1 = new FormBody.Builder();
Set<Map.Entry<String, String>> entries = map.entrySet();//鍵值對(duì)的集合
for (Map.Entry<String, String> entry : entries) {//遍歷集合
String key = entry.getKey();//獲得鍵
String value = entry.getValue();//獲得值
builder1.add(key,value);
}
FormBody formBody = builder1.build();
//TODO 2:request對(duì)象
Request request = new Request.Builder().url(str_url).post(formBody).build();
//TODO 3:call
Call call = okHttpClient.newCall(request);
//TODO 4:加入隊(duì)列 得到response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onError(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
listener.onSuccess(response.body().string());
}
});
}
/***
* @param str_url 網(wǎng)址
* @param path 下載地址
* @param listener 監(jiān)聽
*/
public void download(String str_url, final String path, final MyFileListener listener){
//TODO 1:request對(duì)象
Request request = new Request.Builder()
.url(str_url)
.get()
//③”Accept-Encoding”, “identity”
.header("Accept-Encoding","identity")
.build();
//TODO 2:客戶端發(fā)起連接得到call
Call call = okHttpClient.newCall(request);
//TODO 3:加入隊(duì)列得到response
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onError(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody body = response.body();
//TODO 1:獲得總長(zhǎng)度
long max = body.contentLength();
listener.setMax((int) max);//返回最大值
//TODO 2:得到輸入流
InputStream inputStream = body.byteStream();
FileOutputStream fileOutputStream = new FileOutputStream(path);
byte[] bytes=new byte[1024];
int len=0;
int count=0;
while((len=inputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);
count+=len;
listener.setProgress(count);//通知進(jìn)度
}
listener.onFinish();//通知完成
}
});
}
/****
*
* @param str_url 請(qǐng)求網(wǎng)址
* @param path 上傳文件的路徑
* @param filename 上傳到服務(wù)器那邊生成文件的名稱
* @param type 類型
* @param listener 監(jiān)聽
*/
public void upload(String str_url, String path, String filename,String type, final MyFileListener listener){
//請(qǐng)求體如何設(shè)置
MultipartBody body=new MultipartBody.Builder()
.setType(MultipartBody.FORM)//設(shè)置方式
.addFormDataPart("file",filename, RequestBody.create(MediaType.parse(type),new File(path)))
.build();
//---------------------
Request request=new Request.Builder().url(str_url).post(body).build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.onError(e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
listener.onFinish();
}
});
}
}