Okhttp使用和源码分析二(OkHttp3.x用法)

来源:互联网 发布:马尔可夫矩阵法例题 编辑:程序博客网 时间:2024/06/05 21:50

上一篇介绍了OkHttp2.x的用法,这一篇文章我们来对照OkHttp2.x版本来看看,OkHttp3使用起来有那些变化?

1.使用前准备,Android Studio 配置gradle:

compile 'com.squareup.okhttp3:okhttp:3.2.0'compile 'com.squareup.okio:okio:1.7.0'

添加网络权限:

<uses-permission android:name="android.permission.INTERNET"/>

2.异步GET请求

private void getAsynHttp() {    mOkHttpClient=new OkHttpClient();    Request.Builder requestBuilder = new Request.Builder().url("http://www.baidu.com");    //可以省略,默认是GET请求    requestBuilder.method("GET",null);    Request request = requestBuilder.build();    Call mcall= mOkHttpClient.newCall(request);    mcall.enqueue(new Callback() {        @Override        public void onFailure(Call call, IOException e) {        }        @Override        public void onResponse(Call call, Response response) throws IOException {            if (null != response.cacheResponse()) {                String str = response.cacheResponse().toString();                Log.i("yzw", "cache---" + str);            } else {                response.body().string();                String str = response.networkResponse().toString();                Log.i("yzw", "network---" + str);            }            runOnUiThread(new Runnable() {                @Override                public void run() {                    Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();                }            });        }    });}

与2.x版本并没有什么不同,比较郁闷的是回调仍然不在UI线程。

2.异步POST请求
OkHttp3异步POST请求和OkHttp2.x有一些差别就是没有FormEncodingBuilder这个类,替代它的是功能更加强大的FormBody:

private void postAsynHttp() {     mOkHttpClient=new OkHttpClient();     RequestBody formBody = new FormBody.Builder()             .add("size", "10")             .build();     Request request = new Request.Builder()             .url("http://api.1-blog.com/biz/bizserver/article/list.do")             .post(formBody)             .build();     Call call = mOkHttpClient.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 str = response.body().string();             Log.i("yzw", str);             runOnUiThread(new Runnable() {                 @Override                 public void run() {                     Toast.makeText(getApplicationContext(), "请求成功", Toast.LENGTH_SHORT).show();                 }             });         }     }); }

3.异步上传文件

上传文件本身也是一个POST请求,上一篇没有讲,这里我们补上。首先定义上传文件类型:

public static final MediaType MEDIA_TYPE_MARKDOWN        = MediaType.parse("text/x-markdown; charset=utf-8");

将sdcard根目录的wangshu.txt文件上传到服务器上:

private void postAsynFile() {    mOkHttpClient=new OkHttpClient();    File file = new File("/sdcard/wangshu.txt");    Request request = new Request.Builder()            .url("https://api.github.com/markdown/raw")            .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))            .build();        mOkHttpClient.newCall(request).enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {            }            @Override            public void onResponse(Call call, Response response) throws IOException {                Log.i("yzw",response.body().string());            }        });    }

当然如果想要改为同步的上传文件只要调用 mOkHttpClient.newCall(request).execute()就可以了。
当然不要忘了添加如下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

4.异步下载文件

下载文件同样在上一篇没有讲到,实现起来比较简单,在这里下载一张图片,我们得到Response后将流写进我们指定的图片文件中就可以了。

 private void downAsynFile() {     mOkHttpClient = new OkHttpClient();     String url = "http://img.my.csdn.net/uploads/201603/26/1458988468_5804.jpg";     Request request = new Request.Builder().url(url).build();     mOkHttpClient.newCall(request).enqueue(new Callback() {         @Override         public void onFailure(Call call, IOException e) {         }         @Override         public void onResponse(Call call, Response response) {             InputStream inputStream = response.body().byteStream();             FileOutputStream fileOutputStream = null;             try {                 fileOutputStream = new FileOutputStream(new File("/sdcard/wangshu.jpg"));                 byte[] buffer = new byte[2048];                 int len = 0;                 while ((len = inputStream.read(buffer)) != -1) {                     fileOutputStream.write(buffer, 0, len);                 }                 fileOutputStream.flush();             } catch (IOException e) {                 Log.i("wangshu", "IOException");                 e.printStackTrace();            }            Log.d("wangshu", "文件下载成功");        }    });}

5.异步上传Multipart文件

这种场景很常用,我们有时会上传文件同时还需要传其他类型的字段,OkHttp3实现起来很简单,需要注意的是没有服务器接收我这个Multipart文件,所以这里只是举个例子,具体的应用还要结合实际工作中对应的服务器。
首先定义上传文件类型:

private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");private void sendMultipart(){    mOkHttpClient = new OkHttpClient();    RequestBody requestBody = new MultipartBody.Builder()            .setType(MultipartBody.FORM)            .addFormDataPart("title", "yzw")            .addFormDataPart("image", "yzw.png",                    RequestBody.create(MEDIA_TYPE_PNG, new File("/sdcard/yzw.jpg")))            .build();    Request request = new Request.Builder()            .header("Authorization", "Client-ID " + "...")            .url("https://api.imgur.com/3/image")            .post(requestBody)            .build();   mOkHttpClient.newCall(request).enqueue(new Callback() {       @Override       public void onFailure(Call call, IOException e) {       }       @Override       public void onResponse(Call call, Response response) throws IOException {           Log.i("yzw", response.body().string());       }   });}

6.设置超时时间和缓存

和OkHttp2.x有区别的是不能通过OkHttpClient直接设置超时时间和缓存了,而是通过OkHttpClient.Builder来设置,通过builder配置好OkHttpClient后用builder.build()来返回OkHttpClient,所以我们通常不会调用new OkHttpClient()来得到OkHttpClient,而是通过builder.build():

File sdcache = getExternalCacheDir();int cacheSize = 10 * 1024 * 1024;OkHttpClient.Builder builder = new OkHttpClient.Builder()        .connectTimeout(15, TimeUnit.SECONDS)        .writeTimeout(20, TimeUnit.SECONDS)        .readTimeout(20, TimeUnit.SECONDS)        .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));OkHttpClient mOkHttpClient=builder.build();

7.关于取消请求和封装

取消请求仍旧可以调用call.cancel(),只是这一版中增加了一个cancelAll()的方法:

  /**     * 取消某单个请求任务     */    public void cancelRequest(CharSequence url) {        try {            //任务调度中正在排队的任务            for (Call call : okHttpClient.dispatcher().queuedCalls()) {                if (call.request().tag().equals(url))                    call.cancel();            }            //任务调度中正在执行的任务            for (Call call : okHttpClient.dispatcher().runningCalls()) {                if (call.request().tag().equals(url))                    call.cancel();            }        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 取消全部请求任务     */    public void cancelAllRequest() {        try {            okHttpClient.dispatcher().cancelAll();        } catch (Exception e) {            e.printStackTrace();        }    }

8.封装

public class OkHttp3Engine {    private static OkHttp3Engine mInstance;    private OkHttpClient okHttpClient = null;    private int DEFAULT_HTTP_TIMEOUT = 15_000;    private int SIZE_OF_CACHE = 5 * 1024 * 1024;    private CharSequence StringEncode = "utf-8";    private static final MediaType Json = MediaType.parse("application/json; charset=utf-8");    private static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");    private CharSequence POST = "post";    private CharSequence GET = "get";    private Handler handler = null;    private boolean hasCache = true;    public OkHttp3Engine() {        super();        handler = new Handler(Looper.getMainLooper());        OkHttpClient.Builder builder = new OkHttpClient.Builder();        builder.connectTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        builder.readTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        builder.writeTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        okHttpClient = builder.build();    }    public static OkHttp3Engine getInstance() {        if (mInstance == null) {            synchronized (OkHttp3Engine.class) {                if (mInstance == null) {                    mInstance = new OkHttp3Engine();                }            }        }        return mInstance;    }    public <T> void fetchStringPost(CharSequence url, T resultBean, Map<CharSequence, CharSequence> map, FetchDataInterface fetchDatainterface) {        fetchString(url.toString(), resultBean, map, POST, false, null, fetchDatainterface);    }    public <T> void fetchStringGet(CharSequence url, T resultBean, Map<CharSequence, CharSequence> map, FetchDataInterface fetchDatainterface) {        fetchString(url.toString(), resultBean, map, GET, false, null, fetchDatainterface);    }    public <T> void fetchStringAsyncPost(CharSequence url, T resultBean, Map<CharSequence, CharSequence> map, FetchDataInterface fetchDatainterface) {        AsyncfetchString(url.toString(), resultBean, map, POST, false, null, fetchDatainterface);    }    public <T> void fetchStringAsyncGet(CharSequence url, T resultBean, Map<CharSequence, CharSequence> map, FetchDataInterface fetchDatainterface) {        AsyncfetchString(url.toString(), resultBean, map, GET, false, null, fetchDatainterface);    }    public <T> void fetchStringPostJson(CharSequence url, T resultBean, CharSequence json, FetchDataInterface fetchDatainterface) {        fetchString(url.toString(), resultBean, null, POST, true, json, fetchDatainterface);    }    public <T> void fetchStringAsyncPostJson(CharSequence url, T resultBean, CharSequence json, FetchDataInterface fetchDatainterface) {        AsyncfetchString(url.toString(), resultBean, null, POST, true, json, fetchDatainterface);    }    public void setOkHttpCache(boolean hasCache, Context mContext) {        this.hasCache = hasCache;        File cacheDirectory = new File(mContext.getExternalCacheDir(), "HttpCache");        OkHttpClient.Builder builder = new OkHttpClient.Builder();        builder.connectTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        builder.readTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        builder.writeTimeout(DEFAULT_HTTP_TIMEOUT, TimeUnit.SECONDS);        if (okHttpClient != null) {            okHttpClient.dispatcher().cancelAll();        }        if (hasCache) {            Cache cache = new Cache(cacheDirectory, SIZE_OF_CACHE);            okHttpClient = builder.cache(cache).build();        } else {            okHttpClient = builder.build();        }    }    public boolean isHasCache() {        return hasCache;    }    /**     * 取消某单个请求任务     */    public void cancelRequest(CharSequence url) {        try {            //任务调度中正在排队的任务            for (Call call : okHttpClient.dispatcher().queuedCalls()) {                if (call.request().tag().equals(url))                    call.cancel();            }            //任务调度中正在执行的任务            for (Call call : okHttpClient.dispatcher().runningCalls()) {                if (call.request().tag().equals(url))                    call.cancel();            }        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 取消全部请求任务     */    public void cancelAllRequest() {        try {            okHttpClient.dispatcher().cancelAll();        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 回调接口     */    public interface FetchDataInterface {        <T> void successful(T result);        void failed(CharSequence message);    }    /**     * 同步请求     */    private <T> void fetchString(CharSequence url, T resultBean, Map<CharSequence, CharSequence> map, CharSequence method, boolean isSendJson, CharSequence json, FetchDataInterface fetchDatainterface) {        Request request = null;        try {            if (method.equals(POST)) {                RequestBody body = null;                if (isSendJson) {                    body = RequestBody.create(Json, json.toString());                } else {                    //pMap.put("param", JSONObject.toJSONString(map));                    body = mapToRequestBody(map);                }                if (isHasCache())                    request = new Request.Builder().tag(url).url(new URI(url.toString()).toURL()).post(body).build();                else {                    request = new Request.Builder().tag(url).url(new URI(url.toString()).toURL()).cacheControl(CacheControl.FORCE_CACHE).post(body).build();                }            } else {                //CharSequence param = setMapToParam(map).toString();                if (isHasCache())                    request = new Request.Builder().tag(url).url(new URI(builderGetUri(url.toString(), map).toString()).toURL()).get().build();                else {                    request = new Request.Builder().tag(url).url(new URI(builderGetUri(url.toString(), map).toString()).toURL()).cacheControl(CacheControl.FORCE_CACHE).get().build();                }            }            Response response = okHttpClient.newCall(request).execute();            if (null == response || !response.isSuccessful()) {                sendCallBack("respponse isnull", false, fetchDatainterface);                return;            }            byte[] bytes = response.body().bytes();            if (null == bytes) {                sendCallBack("responsebody isnull", false, fetchDatainterface);                return;            }            String result = new String(bytes, StringEncode.toString());            if (TextUtils.isEmpty(result)) {                sendCallBack("strcode isnull", false, fetchDatainterface);                return;            }            /**             * 判断返回的是否是json格式的数据             */            JSONObject jsonString = JSON.parseObject(result);            T t = (T) JSON.parseObject(jsonString.toString(), resultBean.getClass());            sendCallBack(t, true, fetchDatainterface);        } catch (Exception e) {            e.printStackTrace();            sendCallBack(e.getMessage(), false, fetchDatainterface);        }    }    /**     * 异步请求     */    private <T> void AsyncfetchString(final CharSequence url, final T resultBean, Map<CharSequence, CharSequence> map, CharSequence method, boolean isSendJson, final CharSequence json, final FetchDataInterface fetchDatainterface) {        Request request = null;        try {            if (method.equals(POST)) {                RequestBody body = null;                if (isSendJson) {                    body = RequestBody.create(Json, json.toString());                } else {                    //pMap.put("param", JSONObject.toJSONString(map));                    body = mapToRequestBody(map);                }                if (isHasCache())                    request = new Request.Builder().tag(url).url(new URI(url.toString()).toURL()).post(body).build();                else                    request = new Request.Builder().tag(url).url(new URI(url.toString()).toURL()).cacheControl(CacheControl.FORCE_CACHE).post(body).build();            } else {                //CharSequence param = setMapToParam(map).toString();                if (isHasCache())                    request = new Request.Builder().tag(url).url(new URI(builderGetUri(url.toString(), map).toString()).toURL()).get().build();                else                    request = new Request.Builder().tag(url).url(new URI(builderGetUri(url.toString(), map).toString()).toURL()).cacheControl(CacheControl.FORCE_CACHE).get().build();            }            okHttpClient.newCall(request).enqueue(new Callback() {                @Override                public void onResponse(Call call, Response response) throws IOException {                    if (null == response || !response.isSuccessful()) {                        sendCallBack("response isnull", false, fetchDatainterface);                        return;                    }                    byte[] bytes = response.body().bytes();                    if (null == bytes) {                        sendCallBack("responsebody isnull", false, fetchDatainterface);                        return;                    }                    String result = new String(bytes, StringEncode.toString());                    if (TextUtils.isEmpty(result)) {                        sendCallBack("strcode isnull", false, fetchDatainterface);                        return;                    }                    /**                     * 判断返回的是否是json格式的数据                     */                    try {                        JSONObject jsonString = JSON.parseObject(result);                        T t = (T) JSON.parseObject(jsonString.toString(), resultBean.getClass());                        sendCallBack(t, true, fetchDatainterface);                    } catch (Exception e) {                        e.printStackTrace();                        sendCallBack(e.getMessage(), false, fetchDatainterface);                    }                }                @Override                public void onFailure(Call call, IOException e) {                    sendCallBack(e.getMessage(), false, fetchDatainterface);                }            });        } catch (Exception e) {            e.printStackTrace();            sendCallBack(e.getMessage(), false, fetchDatainterface);        }    }    private RequestBody mapToRequestBody(Map<CharSequence, CharSequence> kv) throws IOException {        FormBody.Builder formBody = new FormBody.Builder();        for (CharSequence key : kv.keySet()) {            formBody.add(key.toString(), kv.get(key).toString());        }        return formBody.build();    }    private CharSequence setMapToParam(Map<CharSequence, CharSequence> hashMap) {        StringBuilder param = new StringBuilder();        if (hashMap == null || hashMap.size() == 0) {            return "";        }        for (Map.Entry<CharSequence, CharSequence> entry : hashMap.entrySet()) {            // 如果请求参数中有中文,需要进行URLEncoder编码            if (entry.getValue() != null) {                try {                    param.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), StringEncode.toString()));                    param.append("&");                } catch (Exception e) {                    e.printStackTrace();                }            }        }        if (param.length() > 0) {            param.deleteCharAt(param.length() - 1);        }        return param.toString();    }    private CharSequence builderGetUri(CharSequence uri, Map<CharSequence, CharSequence> map) {        StringBuilder sb = new StringBuilder();        try {            while (uri.toString().endsWith("/")) {                try {                    uri = uri.toString().substring(0, uri.length() - 1);                } catch (Exception e) {                    e.printStackTrace();                }            }            sb.append(uri).append("?");            if (map != null && map.size() != 0) {                for (Map.Entry<CharSequence, CharSequence> entry : map.entrySet()) {                    // 如果请求参数中有中文,需要进行URLEncoder编码                    sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), StringEncode.toString()));                    sb.append("&");                }                sb.deleteCharAt(sb.length() - 1);            }        } catch (Exception e) {            e.printStackTrace();        }        Log.d("builderGetUri", sb.toString());        return sb.toString();    }    /**     * 文件上传     *     * @param url                上传的服务器地址     * @param file               上传的本地文件     * @param params             上传文件时带的参数     * @param fetchDatainterface 上传完成后的回调接口     */    public void uploadFile(final CharSequence url, File file, Map<String, String> params, final FetchDataInterface fetchDatainterface) {        Request request = new Request.Builder().headers(Headers.of(params)).url(url.toString()).post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file)).build();        Call call = okHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {                sendCallBack(e.getMessage(), false, fetchDatainterface);            }            @Override            public void onResponse(Call call, Response response) throws IOException {                sendCallBack(response.body().string(), true, fetchDatainterface);            }        });    }    /**     * 文件下载     *     * @param url                下载的服务器地址     * @param localSavePath      下载后保存的本地地址     * @param fetchDatainterface 下载完成后的回调接口     */    public void downloadFile(final String url, final String localSavePath, final FetchDataInterface fetchDatainterface) throws Exception {        Request request = new Request.Builder().url(url).build();        okHttpClient.newCall(request).enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {                sendCallBack(e.getMessage(), false, fetchDatainterface);            }            @Override            public void onResponse(Call call, Response response) {                try {                    InputStream inputStream = response.body().byteStream();                    FileOutputStream fileOutputStream = new FileOutputStream(new File(localSavePath));                    byte[] buffer = new byte[2048];                    int len = 0;                    while ((len = inputStream.read(buffer)) != -1) {                        fileOutputStream.write(buffer, 0, len);                    }                    inputStream.close();                    fileOutputStream.flush();                    fileOutputStream.close();                    sendCallBack(localSavePath, true, fetchDatainterface);                } catch (IOException e) {                    Log.i("downloadFile", "IOException");                    e.printStackTrace();                }                Log.d("downloadFile", "文件下载成功");            }        });    }    /**     * 图片下载并展示     *     * @param image 展示的控件     * @param url   下载的地址     */    public void downloadImgShowImageView(final ImageView image, final String url) throws Exception {        Request request = new Request.Builder().url(url).build();        Call call = okHttpClient.newCall(request);        call.enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {                image.setImageResource(0);            }            @Override            public void onResponse(Call call, Response response) throws IOException {                InputStream is = response.body().byteStream();                ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);                ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(image);                int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);                try {                    is.reset();                } catch (Exception e) {                    Request request = new Request.Builder().url(url).build();                    response = okHttpClient.newCall(request).execute();                    is = response.body().byteStream();                }                BitmapFactory.Options ops = new BitmapFactory.Options();                ops.inJustDecodeBounds = false;                ops.inSampleSize = inSampleSize;                final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);                image.post(new Runnable() {                    @Override                    public void run() {                        image.setImageBitmap(bm);                    }                });                is.close();            }        });    }    private <T> void sendCallBack(final T t, final boolean isSccessful, final FetchDataInterface fetchDatainterface) {        handler.post(new Runnable() {            @Override            public void run() {                if (isSccessful)                    fetchDatainterface.successful(t);                else                    fetchDatainterface.failed(t.toString());            }        });    }}

我们以一个get请求为例使用:

OkHttp3Engine.getInstance().fetchStringAsyncGet("http://www.baidu.com", new String(), null, new OkHttp3Engine.FetchDataInterface() {            @Override            public <T> void successful(T result) {                Log.d("yzw", result.toString());            }            @Override            public void failed(CharSequence message) {            }        });

博文参考:http://liuwangshu.cn/application/network/6-okhttp3.html

原创粉丝点击