OkHttp 使用详情一

一概要:

Android已经为我们提供了HttpURLConnection 和 Apache Http Client,能够满足我们各种的Http请求

需求,当时Android SDK依然为我们默认提供了OkHttp。因为OkHttp相对更高效,更省流量。

OkHttp的特点:

1,支持SPDY,共享同一个Socket来处理同一个服务器的所有请求。

2,如果SPDY不可用,则通过连接池来减少请求的延迟。

3,无缝的支持GZIP,来减少数据流量。

4,缓存响应数据,减少重复网络请求。

使用OkHttp需要用到两个jar,OkHttpxxx.jarOkioxxx.jar


二使用:

Http Get 请求

    private static final OkHttpClient client = new OkHttpClient.Builder().build();
    private String get(String url) throws IOException{
        Request request = new Request.Builder().url(url).build();
        Response response = client.newCall(request).execute();
        if(response.isSuccessful()){
            return response.body().string();
        }else{
            throw new IOException("Unexpected code " + response);
        }
    }

Request是OkHttp的访问请求,Builder是辅助类,Response是OkHttp中的响应。


Http Post 请求(提交Json数据)

    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    private String post(String url, String json) throws IOException{
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = client.newCall(request).execute();
        if(response.isSuccessful()){
            return response.body().string();
        }else{
            throw new IOException("Unexpected code " + response);
        }
    }


Http Post 请求(提交键值对)

    private String post(String url, Map<String, String> params) throws IOException{
        FormBody.Builder builder = new FormBody.Builder();
        Iterator<String> iterator =  params.keySet().iterator();
        if(iterator.hasNext()){
            String key = iterator.next();
            //添加键值对
            builder.add(key, params.get(key));
        }
        FormBody body = builder.build();

        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = client.newCall(request).execute();
        if(response.isSuccessful()){
            return response.body().string();
        }else{
            throw new IOException("Unexpected code " + response);
        }
    }


通过上面的例子,我们发现OkHttp使用很方便,但是上面依然有重复代码。这里写一个工具类OkHttpUitl

注意:#OkHttp的官方文档不建议我们创建多个OkHttpClient,因此我们用一个全局变量。

           #enqueue是OkHttp为我们提供的异步方法。

public class OkHttpUtil {

    private static final int READ_TIME_OUT = 30;
    private static final int WRITE_TIME_OUT = 30;
    private static final int CONNECTION_TIME_OUT = 30;
    private static final OkHttpClient client = new OkHttpClient.Builder()
            .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)
            .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)
            .connectTimeout(CONNECTION_TIME_OUT, TimeUnit.SECONDS)
            .build();

    /**
     * 同步任务
     *
     * @param request
     * @return
     * @throws IOException
     */
    public static Response execute(Request request) throws IOException {
        return client.newCall(request).execute();
    }

    /**
     * 异步执行任务
     *
     * @param request
     * @param callback
     */
    public static void enqueue(Request request, Callback callback) {
        client.newCall(request).enqueue(callback);
    }

    /**
     * 获得String 类型的返回值
     * @param url
     * @return
     * @throws IOException
     */
    public static String getStringFromServer(String url) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .build();
        Response response = execute(request);
        if (response.isSuccessful()) {
            return response.body().string();
        }else{
            throw new IOException("Unexpected-code:" + response);
        }
    }
}


File下载(Get)

    /**
     * 下载文件
     * @param url
     * @param path
     */
    private void downloadFile(final String url, String path) {
        Request request = new Request.Builder().url(url).build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtil.i(TAG, "onFailure:" + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                InputStream in = null;
                FileOutputStream fos = null;
                try {
                    String path = "mnt/sdcard/Download/temp.jpg";
                    File file = new File(path);
                    fos = new FileOutputStream(file);
                    if (response.isSuccessful()) {
                        LogUtil.i(TAG, "onResponse success:");
                        in = response.body().byteStream();
                        int len;
                        byte[] buf = new byte[10234];
                        while ((len = in.read(buf)) != -1) {
                            fos.write(buf, 0, len);
                        }
                    } else {
                        LogUtil.i(TAG, "onResponse code:" + response);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (in != null) {try {in.close();} catch (Exception e) {}}
                    if (fos != null) {try {fos.close();} catch (Exception e) {}}
                }
            }
        });
    }

File 上传(Post)

    private String uploadFile(String url, File file) throws IOException{
        RequestBody body = RequestBody.create(MEDIA_TYPE_MARKDOWN, file);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            return response.body().string();
        } else {
            throw new IOException("Unexpected code " + response);
        }
    }


响应缓存:(缓存响应,在没有网络,或者短时间内重复请求时,读取缓存提高效率,减少流量)

        File cacheFile = Util.getCacheFile(context, "okhttp_cache");
        Cache cache = new Cache(cacheFile, 10*1024*1024);//10MB
        client = new OkHttpClient.Builder()
                .cache(cache)  //设置缓存了
                .build();

    private void get(String url) throws IOException {
        Request request1 = new Request.Builder().url(url).build();
        Response response1 = client.newCall(request1).execute();
        if (!response1.isSuccessful()) {
            throw new IOException("Unexpected code " + response1);
        }
        LogUtil.i(TAG, "response:" + response1.body().string());
        LogUtil.i(TAG, "response cache:" + response1.cacheResponse());
        LogUtil.i(TAG, "response network:" + response1.networkResponse());

        Request request2 = new Request.Builder().url(url).build();
        Response response2 = client.newCall(request1).execute();
        if (!response1.isSuccessful()) {
            throw new IOException("Unexpected code " + response2);
        }
        LogUtil.i(TAG, "response:" + response2.body().string());
        LogUtil.i(TAG, "response cache:" + response2.cacheResponse());
        LogUtil.i(TAG, "response network:" + response2.networkResponse());
    }

注意:#设定一个私有的缓存目录(cacheFile),并限定其大小(10*1024*1024); 

          #一个缓存目录对应一个OkHttpClient,否侧会出现错误(没有做并发处理)

          #上面的第一次请求response1.cacheResponse为null,第二次请求response2.networkResponse为null

          #不读取缓存,可以在request build的时设定.cacheControl(CacheControl.ForceNetWork);(等同:)

         #只读取缓存的时,设定.cacheControl(CacheControl.ForceCache);


验证:Http Auth

OkHttp会自动尝试一个未验证额请求,如果返回401 Not Authorized时,如果Client设置了Authenticator,会自动

调用一个带证书的新的请求。如果未设置则跳过尝试返回null。

        client = new OkHttpClient.Builder()
                .cache(cache)
                .authenticator(new Authenticator() {
                    @Nullable
                    @Override
                    public Request authenticate(Route route, Response response) throws IOException {
                        String credential = Credentials.basic("username", "password");
                        return response.request().newBuilder().header("Authorization", credential).build();
                    }
                })
                .build();

参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html

OkHttp拓展:OkHttp 使用详情二

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值