最近工作主要用到OkHttp3.0網(wǎng)絡請求框架,進行Get請求,Post請求,多文件上傳等功能,本文內(nèi)容大部分來源于網(wǎng)上博文,僅做個人總結(jié)記錄
以下內(nèi)容來源其他博文:
在使用OKHttp之前,首先要先了解如下幾個比較核心的類:
OkHttpClient:客戶端對象
Request:訪問請求,Post請求中需要包含RequestBody
RequestBody:請求數(shù)據(jù),在Post請求中用到
Response:即網(wǎng)絡請求的響應結(jié)果
MediaType:數(shù)據(jù)類型,用來表明數(shù)據(jù)是json,image,pdf等一系列格式
client.newCall(request).execute():同步的請求方法
client.newCall(request).enqueue(Callback callBack):異步的請求方法,但Callback是執(zhí)行在子線程中的,因此不能在此進行UI更新操作
GitHub地址
OkHttp的GitHub地址是:OkHttp
OkIo的GitHub地址是:OkIo
依賴庫導入
使用前需要先在項目中添加OkHttp的依賴庫,在對應的Module的gradle中添加如下語句,目前最新應該是3.7.0
compile 'com.squareup.okhttp3:okhttp:3.7.0'
此外,OkHttp內(nèi)部以來另外一個開源庫Oklo
compile 'com.squareup.okio:okio:1.12.0'
添加網(wǎng)絡權限
<uses-permission android:name="android.permission.INTERNET"/>
一、GET請求
OkHttp支持同步和異步的網(wǎng)絡請求,demo代碼如下:
同步GET請求
//1.創(chuàng)建OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
//2.創(chuàng)建Request對象,設置一個url地址(百度地址),設置請求方式。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.get()
.build();
//3.創(chuàng)建一個call對象,參數(shù)就是Request請求對象
Call call = okHttpClient.newCall(request);
//4.同步調(diào)用會阻塞主線程,這邊在子線程進行
new Thread(new Runnable() {
@Override
public void run() {
try {
//同步調(diào)用,返回Response,會拋出IO異常
Response response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
異步GET請求
//1.創(chuàng)建OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
//2.創(chuàng)建Request對象,設置一個url地址(百度地址),設置請求方式。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.get()
.build();
//3.創(chuàng)建一個call對象,參數(shù)就是Request請求對象
Call call = okHttpClient.newCall(request);
//4.請求加入調(diào)度,重寫回調(diào)方法
call.enqueue(new Callback() {
//請求失敗執(zhí)行的方法
@Override
public void onFailure(Call call, IOException e) {
String err = e.getMessage().toString();
}
//請求成功執(zhí)行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
final String rtn = response.body().string();
runOnUiThread(new Runnable() {
@Override
public void run() {
}
);
}
});
需要注意的是,異步調(diào)用的回調(diào)函數(shù)是在子線程當中的,因為需要用Handler或者runOnUiThread來更新UI
二、POST類型
在OkHttp中用Post方法向服務器發(fā)送一個請求體時,請求體需要是一個RequestBody。這個請求體可以是:
key-value:鍵值對類型
String:字符串類型
Form:類似于Html的表單數(shù)據(jù)提交
Stream:流類型
File:文件類型
三、Post 鍵值對
//1.創(chuàng)建OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
FormBody.Builder mBuild = new FormBody.Builder();
mBuild.add("aa", "bb")
.add("cc", 1);
RequestBody requestBodyPost = mBuild.build();
//2.創(chuàng)建Request對象,設置一個url地址(百度地址),設置請求方式。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBodyPost )
.build();
//3.創(chuàng)建一個call對象,參數(shù)就是Request請求對象
Call call = okHttpClient.newCall(request);
//4.請求加入調(diào)度,重寫回調(diào)方法
call.enqueue(new Callback() {
//請求失敗執(zhí)行的方法
@Override
public void onFailure(Call call, IOException e) {
String err = e.getMessage().toString();
}
//請求成功執(zhí)行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
final String rtn = response.body().string();
//獲取返回碼
final String code = String.valueOf(response.code())
runOnUiThread(new Runnable() {
@Override
public void run() {
}
);
}
});
四、Post 字符串
有時候我們會有要傳送字符串的需要,比如向服務器發(fā)送一個JSON字符串。那么就可以用如下方法:
//1.創(chuàng)建OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient();
//RequestBody中的MediaType指定為純文本,編碼方式是utf-8
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain;charset=utf-8"),
"{username:admin;password:admin}");
//2.創(chuàng)建Request對象,設置一個url地址(百度地址),設置請求方式。
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(requestBody )
.build();
//3.創(chuàng)建一個call對象,參數(shù)就是Request請求對象
Call call = okHttpClient.newCall(request);
//4.請求加入調(diào)度,重寫回調(diào)方法
call.enqueue(new Callback() {
//請求失敗執(zhí)行的方法
@Override
public void onFailure(Call call, IOException e) {
String err = e.getMessage().toString();
}
//請求成功執(zhí)行的方法
@Override
public void onResponse(Call call, Response response) throws IOException {
final String rtn = response.body().string();
//獲取返回碼
final String code = String.valueOf(response.code())
runOnUiThread(new Runnable() {
@Override
public void run() {
}
);
}
});
也可以直接Post Json數(shù)據(jù)
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url("http://www.baidu.com")
.post(body)
.build();
...
五、Post提交表單
OkHttpClient client = new OkHttpClient();
MultipartBody.Builder mBuild = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("username", "xxx")
.addFormDataPart("password", "xxx");
RequestBody requestBody= mBuild.build();
final Request request = new Request.Builder()
.url("http://www.lxweimin.com/")
.post(requestBody)
.build();
...
六、Post提交多文件
OkHttpClient http = new OkHttpClient();
MultipartBody.Builder mBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
int i = 0;
for(String filePath :filelist) {
File file = new File(filePath);
if (!file.exists()){
Toast.makeText(MainActivity.this,"上傳"+filePath+"文件不存在!", Toast.LENGTH_SHORT).show();
continue;
}
String fileMimeType = getMimeType(file);
//這里獲取文件類型,方法自己定義
MediaType mediaType = MediaType.parse(fileMimeType);
RequestBody fileBody = RequestBody.create(mediaType, file);
mBody.addFormDataPart("file" + i, file.getName(), fileBody);
i++;
}
RequestBody requestBody = mBody.build();
Request requestPostFile = new Request.Builder()
.url("http://www.lxweimin.com/")
.post(requestBody)
.build();
...
android獲取文件getMimeType的方法
private static String getSuffix(File file) {
if (file == null || !file.exists() || file.isDirectory()) {
return null;
}
String fileName = file.getName();
if (fileName.equals("") || fileName.endsWith(".")) {
return null;
}
int index = fileName.lastIndexOf(".");
if (index != -1) {
return fileName.substring(index + 1).toLowerCase(Locale.US);
} else {
return null;
}
}
public static String getMimeType(File file){
String suffix = getSuffix(file);
if (suffix == null) {
return "file/*";
}
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(suffix);
if (type != null || !type.isEmpty()) {
return type;
}
return "file/*";
}
同時上傳文件加上鍵值對參數(shù)的方法:
RequestBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.ALTERNATIVE)
.addFormDataPart("aa","bb")
.addFormDataPart("cc",1)
.addFormDataPart("file",filename,fileBody)*/
.build();
七、下載圖片
OkHttpClient client = new OkHttpClient();
final Request request = new Request
.Builder()
.get()
.url("http://avatar.csdn.net/B/0/1/1_new_one_object.jpg")
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
ToastUtil.showToast(DownImageActivity.this, "下載圖片失敗");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
InputStream inputStream = response.body().byteStream();
//將圖片顯示到ImageView中
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
runOnUiThread(new Runnable() {
@Override
public void run() {
iv_result.setImageBitmap(bitmap);
}
});
//將圖片保存到本地存儲卡中
File file = new File(Environment.getExternalStorageDirectory(), "image.png");
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] temp = new byte[128];
int length;
while ((length = inputStream.read(temp)) != -1) {
fileOutputStream.write(temp, 0, length);
}
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
}
});
指定圖片地址并下載成功后,獲取圖片的輸入流,先用Bitmap decodeStream(InputStream is)方法將輸入流轉(zhuǎn)為Bitmap然后顯示出來,然后將圖片保存到本地存儲卡根目錄下
記得要申請存儲卡的寫權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
參考博文
Android OkHttp的基本用法
Android 網(wǎng)絡編程之最新OKHTTP:3.9.0
android獲取文件getMimeType的方法