OKHttp 使用

Android网络请求框架很多,为什么我选择的是Okhttp?
也许是不经意之间听到Android4.4的源码里面都用了她,又或者是她支持Google开发的SPDY协议,
又或者她来自鼎鼎大名的Square?

其实我也不知道,就想试一下;
在使用过程出现很多问题,相比于那些成熟的网络框架, 体现出来的是OkHttp相当于HttpClient和HttpURLConnection这种底层一点的,而其余的所有网络请求框架基本都是对HttpClient和HttpURLConnection封装,所以很多框架都在网络请求上可以用她来作为底层,Volley可以用她再来作为底层的网络请求,Fresco也可以,在Fresco的一个Demo中,Fresco+OkHttp速度最快,不知道是不是偶然,我自己测试是如此,等等其他很多。

在当前项目中使用的是这个,所以为了方便处理,做了一些封装,有自己的封装也有参考网上资料的,整合力一下。

先看几个请求方式和请求结果 gif是按照顺序来操作

demo效果

文件上传的log细节
上传log

文件下载的log细节
下载log

先看看对OkHttp使用的封装

public class OkHttpUtil {
    public static final OkHttpClient mOkHttpClient = new OkHttpClient();

    static {
        mOkHttpClient.setConnectTimeout(30, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
    }

    //自定义接口 目的是在调用的地方可以直接更新UI
    public interface MyCallBack {
        void onFailure(Request request, IOException e);
        void onResponse(String json);
    }

    //配置OKHttp的Cookie策略,有些地方需要做一些cookie相关的操作
    public static void setCookie(CookieManager cookieManager) {
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        mOkHttpClient.setCookieHandler(cookieManager);
    }

    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");


    /**
     * 异步回调方式 请求  自定义回调接口  结果运行在UI线程
     */
    public static void postData2Server(final Activity activity, Request request, final MyCallBack myCallBack) {
        final String url = request.urlString();
        try {
            mOkHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(final Request request, final IOException e) {
                    if (activity == null) {
                        return;
                    }
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            myCallBack.onFailure(request, e);
                        }
                    });
                }

                @Override
                public void onResponse(Response response) throws IOException {
                    final String json = response.body().string();
                    if (activity == null) {
                        return;
                    }
                    //直接更新UI
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            myCallBack.onResponse(json);
                        }
                    });
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * Daemon
     * -----------------一开始没有发现好的封装对于上传和下载  
     * 就用的下面的两个方法  后面发现在OKHttp的sample中有相关的例子 然后网上也有人写 就借鉴过来了
     * --------------------所以这两个就没用了-----------------------------------------------
     */

    /**
     * 下载显示进度的方法1
     *
     * @param url
     */
    public static void dowloadProgress(Context context, final String url) {

        Request request = new Request.Builder().url(url)
                .build();
        new AsyncDownloader(context).execute(request);

    }

    private static class AsyncDownloader extends AsyncTask<Request, Long, Boolean> {

        private Context context;

        public AsyncDownloader(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Request... params) {

            Call call = mOkHttpClient.newCall(params[0]);
            try {
                Response response = call.execute();
                if (response.code() == 200) {
                    InputStream inputStream = null;
                    OutputStream output = null;
                    try {
                        inputStream = response.body().byteStream();
                        File file = new File(context.getCacheDir(), "download.liubo");
                        output = new FileOutputStream(file);

                        byte[] buff = new byte[1024 * 4];
                        long downloaded = 0;
                        long target = response.body().contentLength();

                        publishProgress(0L, target);
                        while (true) {
                            int readed = inputStream.read(buff);
                            if (readed == -1) {
                                break;
                            }
                            //write buff
                            output.write(buff, 0, readed);

                            downloaded += readed;
                            publishProgress(downloaded, target);

                            if (isCancelled()) {
                                return false;
                            }
                        }
                        output.flush();

                        return downloaded == target;
                    } catch (IOException ignore) {
                        return false;
                    } finally {
                        if (inputStream != null) {
                            inputStream.close();
                        }
                        if (output != null) {
                            output.close();
                        }
                    }
                } else {
                    return false;
                }
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        @Override
        protected void onProgressUpdate(Long... values) {

            LogUtils.e(String.format("%d / %d", values[0], values[1]));

        }

        @Override
        protected void onPostExecute(Boolean result) {
            //下载完成后
        }
    }

    /**
     * 上传文件方法1   进度显示
     */
    public static RequestBody createCustomRequestBody(final MediaType contentType, final File file) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return contentType;
            }

            @Override
            public long contentLength() {
                return file.length();
            }

            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                Source source = null;
                try {
                    source = Okio.source(file);
                    //sink.writeAll(source);
                    Buffer buf = new Buffer();
                    Long remaining = contentLength();
                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
                        sink.write(buf, readCount);
                        LogUtils.e("source size: " + contentLength() + " remaining bytes: " + (remaining -= readCount));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
    }
}

这里是一些OKHttp使用中的一些操作

//如果json body这么构建

 RequestBody body = RequestBody.create(JSON, json);
 如果获取sessionID
Map<String, List<String>> map = new HashMap<String, List<String>>();
//获取cookie 然后打印  绑定
try {
BaseRequest.Cookies = response.headers().get("Set-Cookie");
Logger.getLogger().e(response.headers().toString());
map = mOkHttpClient.getCookieHandler().get(URI.create(url),   response.headers().toMultimap());
for (String key : map.keySet()) {
syso(key + " --  " + map.get(key).toString());
if ("Cookie".equals(key)) {
sessionId = map.get(key).get(0);
}
}
} catch (IOException e) {
e.printStackTrace();
}
 在请求的时候带上cookie  在Request构建的时候加上头部就行
.addHeader("cookie", sessionId)

其实很简单 只是新增一个接口 让其可以UI更新
其实大家看到了 上面有两个方法一个是 下载的进度显示和一个上传的进度显示 这是以前使用的 也能达到效果
后面有一天在微博看到相关的封装 对已上传和下载的进度显示 就集成进来项目中

okhttp结构

红线部分是对于上传和下载的进度显示的类和接口
这里的话 去看这个吧 我是从这个看到的写的挺好的
http://blog.youkuaiyun.com/sbsujjbcy/article/details/48194701
或者这个也行 官方的demo
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/com/squareup/okhttp/recipes/Progress.java

然后看看在整个项目中的一些设置
有BaseActivity的ondestyoy中的 请求取消

    public class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        OkHttpUtil.mOkHttpClient.cancel(this);
    }
}

//MyApplication的oncreate中的okhttp的cookie的设置

public class MyApplication extends Application {
    private static Context mInstance;
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = getBaseContext();
        //cookie策略 让OkHttp接受所有的cookie
        CookieManager cookieManager = new CookieManager();
        OkHttpUtil.setCookie(cookieManager);
    }

    public static Context getContext() {
        return mInstance;
    }
    }

实际运用

/**
* 数据获取Get请求
*/

  Request request
            = new Request.Builder().url("http://www.baidu.com")
            .tag(this)
            .build();

    OkHttpUtil.postData2Server(this, request, new OkHttpUtil.MyCallBack() {
        @Override
        public void onFailure(Request request, IOException e) {

        }

        @Override
        public void onResponse(String json) {
            showData(json);

        }
    });

/**
* 数据上传 Post请求
*/

 RequestBody requestBody = new FormEncodingBuilder()
            .add("action_flag", "user_login")
            .add("mobile_phone", "18566757335")
            .add("user_password", "liubo123")
            .build();

    Request request = new Request.Builder()
            .post(requestBody)
            .url("登陆接口")
            .tag(this)
            .build();

    OkHttpUtil.postData2Server(this, request, new OkHttpUtil.MyCallBack() {
        @Override
        public void onFailure(Request request, IOException e) {

        }

        @Override
        public void onResponse(String json) {
            showData(json);
        }
    });

/**
* 图片下载
*/

    UIProgressResponseListener uiProgressResponseListener = new UIProgressResponseListener() {
        @Override
        public void onUIResponseProgress(long bytesRead, long contentLength, boolean done) {
            LogUtils.e("bytesRead:" + bytesRead);
            LogUtils.e("contentLength:" + contentLength);
            LogUtils.e("done:" + done);

            if (contentLength != -1) {
                // LogUtils.e( (100 * bytesRead) / contentLength + "% done");
            }
            LogUtils.e("================================");
            //ui层回调
            tvshow.setText("下载进度 " + ((100 * bytesRead) / contentLength) + "%");
        }
    };

    //构造请求
    final Request request1 = new Request.Builder()
            .url("网上资源接口")
            .build();

    //包装Response使其支持进度回调
    ProgressHelper.addProgressResponseListener(OkHttpUtil.mOkHttpClient, uiProgressResponseListener)
            .newCall(request1)
            .enqueue(new Callback() {
                         @Override
                         public void onFailure(Request request, IOException e) {
                             Log.e("TAG", "error ", e);
                         }

                         @Override
                         public void onResponse(Response response) throws IOException {
                             InputStream inputStream = null;
                             OutputStream output = null;
                             try {
                                 inputStream = response.body().byteStream();
                                 file = new File(getCacheDir(), "download.jpg");
                                 output = new FileOutputStream(file);
                                 byte[] buff = new byte[1024 * 4];
                                 while (true) {
                                     int readed = inputStream.read(buff);
                                     if (readed == -1) {
                                         break;
                                     }
                                     //write buff
                                     output.write(buff, 0, readed);
                                 }
                                 output.flush();
                             } catch (IOException e) {
                                 file = null;
                                 e.printStackTrace();
                             } finally {
                                 if (inputStream != null) {
                                     inputStream.close();
                                 }
                                 if (output != null) {
                                     output.close();
                                 }
                             }
                         }
                     }
            );

/**
* 图文上传
*/

private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
    if (file == null) {
        ToastUtil.showToast("先下载图片在试着上传吧");
        return;
    }
    tvshow.setText("");

    MultipartBuilder mb = new MultipartBuilder();
    mb.type(MultipartBuilder.FORM);
    mb.addFormDataPart("user_id", "74");
    mb.addFormDataPart("user_head", "user_head.jpg", RequestBody.create(MEDIA_TYPE_PNG, file));
    RequestBody requestBody = mb.build();

    UIProgressRequestListener progressListener = new UIProgressRequestListener() {

        @Override
        public void onUIRequestProgress(long bytesWrite, long contentLength, boolean done) {
            Log.e("TAG", "bytesWrite:" + bytesWrite);
            Log.e("TAG", "contentLength" + contentLength);
            Log.e("TAG", (100 * bytesWrite) / contentLength + " % done ");
            Log.e("TAG", "done:" + done);
            Log.e("TAG", "================================");

            tvshow.setText("上传进度 " + ((100 * bytesWrite) / contentLength) + "%");

        }
    };

    Request request = new Request.Builder()
            .url("上传的接口")
            .post(new ProgressRequestBody(requestBody, progressListener))
            .tag(this)
            .build();

    OkHttpUtil.postData2Server(this, request, new OkHttpUtil.MyCallBack() {
        @Override
        public void onFailure(Request request, IOException e) {

        }

        @Override
        public void onResponse(String json) {

        }
    });

//数据的显示

    private void showData(String json) {
        tvshow.setText("");
        tvshow.setText(json);
    }

以上就是四个例子的使用方法
关于Json的上传和cookie的使用在OkHttpUtil的注释里面有介绍
因为我写demo的效果都是用的公司的接口 所以上面把接口都给取消 需要的自己把接口加上去才能使用

demo上传到http://download.youkuaiyun.com/detail/liubo080852/9094387
有需要的可以下载哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值