初识okHttp

参考文章:
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();
    }

下一篇将分享我在使用时的封装。

发布了37 篇原创文章 · 获赞 0 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章