參考文章:
http://blog.csdn.net/lmj623565791/article/details/47911083
- okHttp提供的方法有以下幾點(從上述文章中摘抄而來):
- 一般的get請求
- 一般的post請求
- 基於Http的文件上傳
- 文件下載
- 加載圖片
- 支持請求回調,直接返回對象、對象集合
- 支持session的保持
1. get請求
//創建okHttpClient對象
OkHttpClient mOkHttpClient = new OkHttpClient();
//創建一個Request
final Request request = new Request.Builder()
.url("https://github.com/hongyangAndroid")
.build();
//new call
Call call = mOkHttpClient.newCall(request);
//請求加入調度
call.enqueue(new Callback()
{
@Override
public void onFailure(Request request, IOException e)
{
}
@Override
public void onResponse(final Response response) throws IOException
{
//String htmlStr = response.body().string();
//調用主線程更新UI,mainHandler是Activity的變量,直接拷貝代碼會報錯,後面會提供demo下載
mainHandler.post(new Runnable(){
public void run() {
ImageView view5 = findView(R.id.imageview2);
view5.setImageBitmap(ImageUtils.getLoacalBitmap(abstractPath));
TextView view1 = findView(R.id.result5);
view1.setText("存儲位置:"+abstractPath);
}
});
}
});
異步執行的是:
call.enqueue(new Callback() {//方法實現});
同步請求:我在UI主線程直接調用同步請求時候報錯了,而在子線程中執行同步請求時成功了,這裏沒太搞明白。突然想到,我是測試時是在onCreate中直接調用同步GET請求,有可能是請求返回了,接着就要更新UI,而這時還沒有出onCreate方法,渲染尚未完成,更新UI就這樣報錯了,不知道是否正確,待後面驗證。
Response mResponse = call.execute();
2.POST請求
Request request = buildMultipartFormRequest(
url, new File[]{file}, new String[]{fileKey}, null);
FormEncodingBuilder builder = new FormEncodingBuilder();
builder.add("username","張三");
Request request = new Request.Builder().url(url).post(builder.build()).build();
mOkHttpClient.newCall(request).enqueue(new Callback(){
@Override
public void onFailure(Request request, IOException e) {
//返回主線程提示失敗信息
}
@Override
public void onResponse(Response response) throws IOException {
//同get請求返回處理方式
}
});
與get請求區別就是需要添加額外參數
FormEncodingBuilder builder = new FormEncodingBuilder();
builder.add("username","張三");
Request request = new Request.Builder().url(url).post(builder.build()).build();
3. 文件上傳
文件上傳使用與POST請求類似,只是POST的參數形式不一樣而已。
File file = new File(Environment.getExternalStorageDirectory(), "balabala.mp4");
RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(Headers.of("Content-Disposition", "form-data; name=\"username\""),
RequestBody.create(null, "李四"))
.addPart(Headers.of("Content-Disposition", "form-data; name=\"mFile\";
filename=\"wjd.mp4\""), fileBody)
.build();
Request request = new Request.Builder()
.url("http://192.168.1.100:8080/okHttpDemo/fileUpload")
.post(requestBody)
.build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback(){
@Override
public void onFailure(Request request, IOException e) {
//
}
@Override
public void onResponse(Response response) throws IOException {
//
}
});
4. 文件下載
文件下載實際就是直接訪問文件網絡地址,,返回後從Response拿到數據流程,保存本地即可。
final Request request = new Request.Builder().url(url).build();
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
currentActivity.httpError(url, new HashMap());
}
@Override
public void onResponse(Response response) {
InputStream is = null;
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos = null;
try {
//拿到數據流程
is = response.body().byteStream();
//根據指定的存放位置創建文件,用以保存下載的文件
File file = new File(destFileDir, getFileName(url));
//建立輸出流
fos = new FileOutputStream(file);
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.flush();
Map params = new HashMap<>();
//currentActivity是調用方法傳過來的當前UI所在界面。
currentActivity.completeDownload(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
currentActivity.httpError(url, new HashMap(), e);
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {
}
try {
if (fos != null) fos.close();
} catch (IOException e) {
}
}
}
});
5. 展示網絡圖片
和文件下載原理一樣的,拿到數據流後,直接創建Bitmap,顯示到指定ImageView即可。
public void displayImage(final Handler mHandler, final ImageView view, final String imgUrl, final int errorResId) {
final Request request = new Request.Builder().url(imgUrl).build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
mHandler.post(new Runnable() {
@Override
public void run() {
view.setImageResource(errorResId);
}
});
}
@Override
public void onResponse(Response response) {
InputStream is = null;
try {
is = response.body().byteStream();
ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);
ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(view);
int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);
try {
is.reset();
} catch (IOException e) {
response = _getAsyn(imgUrl);
is = response.body().byteStream();
}
BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inJustDecodeBounds = false;
ops.inSampleSize = inSampleSize;
final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);
mHandler.post(new Runnable() {
@Override
public void run() {
view.setImageBitmap(bm);
}
});
} catch (Exception e) {
setErrorResId(mHandler, view, errorResId);
} finally {
if (is != null) try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
});
}
另附上圖片處理工具類,某位大神封裝的,是誰沒記住,這裏分享同來
package com.mydemo.okhttp;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.lang.reflect.Field;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
*/
public class ImageUtils {
/**
* 根據InputStream獲取圖片實際的寬度和高度
*/
public static ImageSize getImageSize(InputStream imageStream) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(imageStream, null, options);
return new ImageSize(options.outWidth, options.outHeight);
}
public static class ImageSize {
int width;
int height;
public ImageSize() {
}
public ImageSize(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public String toString() {
return "ImageSize{" + "width=" + width + ", height=" + height + '}';
}
}
public static int calculateInSampleSize(ImageSize srcSize, ImageSize targetSize) {
// 源圖片的寬度
int width = srcSize.width;
int height = srcSize.height;
int inSampleSize = 1;
int reqWidth = targetSize.width;
int reqHeight = targetSize.height;
if (width > reqWidth && height > reqHeight) {
// 計算出實際寬度和目標寬度的比率
int widthRatio = Math.round((float) width / (float) reqWidth);
int heightRatio = Math.round((float) height / (float) reqHeight);
inSampleSize = Math.max(widthRatio, heightRatio);
}
return inSampleSize;
}
/**
* 根據ImageView獲適當的壓縮的寬和高
*/
public static ImageSize getImageViewSize(View view) {
ImageSize imageSize = new ImageSize();
imageSize.width = getExpectWidth(view);
imageSize.height = getExpectHeight(view);
return imageSize;
}
/**
* 根據view獲得期望的高度
*/
private static int getExpectHeight(View view) {
int height = 0;
if (view == null) return 0;
final ViewGroup.LayoutParams params = view.getLayoutParams();
// 如果是WRAP_CONTENT,此時圖片還沒加載,getWidth根本無效
if (params != null && params.height != ViewGroup.LayoutParams.WRAP_CONTENT) {
height = view.getWidth(); // 獲得實際的寬度
}
if (height <= 0 && params != null) {
height = params.height; // 獲得佈局文件中的聲明的寬度
}
if (height <= 0) {
height = getImageViewFieldValue(view, "mMaxHeight");// 獲得設置的最大的寬度
}
// 如果寬度還是沒有獲取到,憋大招,使用屏幕的寬度
if (height <= 0) {
DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
height = displayMetrics.heightPixels;
}
return height;
}
/**
* 根據view獲得期望的寬度
*/
private static int getExpectWidth(View view) {
int width = 0;
if (view == null) return 0;
final ViewGroup.LayoutParams params = view.getLayoutParams();
// 如果是WRAP_CONTENT,此時圖片還沒加載,getWidth根本無效
if (params != null && params.width != ViewGroup.LayoutParams.WRAP_CONTENT) {
width = view.getWidth(); // 獲得實際的寬度
}
if (width <= 0 && params != null) {
width = params.width; // 獲得佈局文件中的聲明的寬度
}
if (width <= 0)
{
width = getImageViewFieldValue(view, "mMaxWidth");// 獲得設置的最大的寬度
}
// 如果寬度還是沒有獲取到,憋大招,使用屏幕的寬度
if (width <= 0)
{
DisplayMetrics displayMetrics = view.getContext().getResources().getDisplayMetrics();
width = displayMetrics.widthPixels;
}
return width;
}
/**
* 通過反射獲取imageview的某個屬性值
*/
private static int getImageViewFieldValue(Object object, String fieldName) {
int value = 0;
try {
Field field = ImageView.class.getDeclaredField(fieldName);
field.setAccessible(true);
int fieldValue = field.getInt(object);
if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
value = fieldValue;
}
} catch (Exception e) {
}
return value;
}
public static Bitmap getLoacalBitmap(String url) {
try {
FileInputStream fis = new FileInputStream(url);
return BitmapFactory.decodeStream(fis);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
獲取sdcard位置,及不限層級創建文件夾方法
public static String getSDPath() {
File sdDir = null;
boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);// 判斷sd卡是否存在
if (sdCardExist) {
sdDir = Environment.getExternalStorageDirectory();// 獲取跟目錄
}
return sdDir.toString();
}
public static String mkdirs(String path) {
String sdcard = getSDPath();
if (path.indexOf(getSDPath()) == -1) {
path = sdcard + (path.indexOf("/") == 0 ? "" : "/") + path;
}
File destDir = new File(path);
if (!destDir.exists()) {
path = createDir(path);
if (path == null) {
return null;
}
}
return path;
}
private static String createDir(String path) {
String sdPath = getSDPath();
String[] dirs = path.replace(sdPath, "").split("/");
StringBuffer filePath = new StringBuffer(sdPath);
for (String dir : dirs) {
if (!"".equals(dir) && !dir.equals(sdPath)) {
filePath.append("/").append(dir);
File destDir = new File(filePath.toString());
if (!destDir.exists()) {
boolean b = destDir.mkdirs();
if (!b) {
return null;
}
}
}
}
return filePath.toString();
}
下一篇將分享我在使用時的封裝。