参考文章:
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();
}
下一篇将分享我在使用时的封装。