android http——OkHttp使用详解
16lz
2021-01-24
okhttp已经被google认定为推荐的android请求框架,我们也可以在as中直接加入:
okhttp的依赖库是:
compile 'com.squareup.okhttp:okhttp:2.5'
当然,作为eclipse的开发者来说,就不能使用依赖库了。
有位同行在博客中写了okhttp的官方文档,可以看看。
我着重介绍okhttp的使用方法。
我们将okhttp所有的网络请求方式都写在RequestHandle类中。
需要注意的几点是,
1,RequestHandle使用单例。因为okhttp使用单例来操作实例。
2,线程阻塞方式的请求需要在非ui线程中。
3,异步回调结果还处在非ui线程中,所以如果要更新ui,需要handler。
1,将RequestHandle写成单例模式:
/** * 单例请求网络,只能传入baseactivity */ private static volatile RequestHandle requestHandle = null; public synchronized static RequestHandle getRequestInterface() { if (requestHandle == null) { synchronized (RequestHandle.class) { if (requestHandle == null) { requestHandle = new RequestHandle(); } } } return requestHandle; }
2,定义常量和初始化对象
//创建队列,用于异步调用 private Request request; //线程阻塞方式调用 private Response response; //访问对象 private Call call; //okhttp实例 private OkHttpClient mOkHttpClient; //线程阻塞方式请求的get,post状态码 private final static int GET_INSTANCE = 0; private final static int POST_INSTANCE = 1; //默认超时时间 private final static int VALUE_DEFAULT_TIME_OUT = 20 * 1000; /** * 参数类型 * "text", 文本 * "image", 图片 * "audio",音频 * "video",视频 * "object",其他 */ private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/x-markdown; charset=utf-8"); private static final MediaType MEDIA_TYPE_JPG = MediaType.parse("image/png"); private static final MediaType MEDIA_TYPE_AUDIO = MediaType.parse("audio/mp3"); private static final MediaType MEDIA_TYPE_VIDEO = MediaType.parse("video/mp4"); private static final MediaType MEDIA_TYPE_OBJECT = MediaType.parse("application/octet-stream"); private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");//给每个网络请求的标记 public static final String TAG_DATA = "tag_data"; public static final String TAG_IMAGE = "tag_image"; public static final String TAG_FILE = "tag_file";private RequestHandle() { //创建okHttpClient对象 mOkHttpClient = new OkHttpClient(); mOkHttpClient.setConnectTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//连接超时 mOkHttpClient.setReadTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//读取超时 mOkHttpClient.setWriteTimeout(VALUE_DEFAULT_TIME_OUT, TimeUnit.MILLISECONDS);//写入超时 }
3,线程阻塞的请求,即非异步的。
get请求
/** * 线程阻塞的单例发送get请求,线程阻塞的方式需要在非ui线程中 */ public void sendGetRequestBlocking(String url) { try { //创建一个请求 request = new Request .Builder() .tag(TAG_DATA) .url(url) .build(); response = mOkHttpClient.newCall(request).execute(); callBackByEnqueueBlocking(response); } catch (IOException e) { e.printStackTrace(); return; } }
post请求:
/** * 异步的post请求,线程阻塞的方式需要在非ui线程中 * * @param url 请求地址 * @param builder 请求参数 */ public void sendPostRequestBlocking(String url, MultipartBuilder builder) { sendPostRequestBlocking(url, builder, null); }
post上传文件:
/**异步的post请求,线程阻塞的方式需要在非ui线程中,可以附带文件 * @param url * @param builder * @param files */ public void sendPostRequestBlocking(String url, MultipartBuilder builder, File[] files) { try { //builder.addFormDataPart("参数", "值"); if (files != null && files.length != 0) { //遍历file数组,得到所有file文件 for (File file : files) { builder.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_OBJECT, file)); } } String tag = files == null ? TAG_DATA : TAG_FILE; request = new Request.Builder() .url(url) .tag(tag) .post(builder.build()) .build(); response = mOkHttpClient.newCall(request).execute(); callBackByEnqueueBlocking(response); } catch (IOException e) { e.printStackTrace(); } }
线程阻塞请求的结果处理:
//队列请求(线程阻塞)的结果处理方法 public void callBackByEnqueueBlocking(Response response) { try { //判断是否是成功的 if (response.isSuccessful()) { //成功 //String jsonStr=response.body().string();//字符串,无编码 String jsonStr = new String(response.body().bytes(), "UTF-8");//二进制字节数组 //InputStream inputStream=response.body().byteStream();//输入流 try { JSONObject jsonObject = new JSONObject(jsonStr); //解析数据处理 //发送数据处理 } catch (JSONException e) { e.printStackTrace(); } } else { //失败 response.code();//失败码 response.message();//失败信息 } } catch (IOException e) { e.printStackTrace(); } }
4,异步请求
get请求
/** * 异步get请求 * * @param url 请求的哪个接口,异步请求 */ public void sendGetRequest(String url) { //创建一个Request request = new Request.Builder() .url(url) .tag(TAG_DATA) .build(); call = mOkHttpClient.newCall(request); callBackByEnqueue(call); }
post请求
/** * 异步的post请求 */ public void sendPostRequest(String url, MultipartBuilder builder) { sendPostRequest(url, builder, null); }
post上传文件
/** 异步的post请求,传文件 * @param url * @param builder * @param files */ public void sendPostRequest(String url, MultipartBuilder builder, File[] files) { //builder.addFormDataPart("参数", "值"); if (files != null && files.length != 0) { //遍历file数组,得到所有file文件 for (File file : files) { builder.addFormDataPart("file", file.getName(), RequestBody.create(MEDIA_TYPE_OBJECT, file)); } } String tag = files == null ? TAG_DATA : TAG_FILE; request = new Request.Builder() .url(url) .tag(tag) .post(builder.build()) .build(); call = mOkHttpClient.newCall(request); callBackByEnqueue(call); }
异步请求结果回调处理:
//队列请求(异步)的结果处理方法 public void callBackByEnqueue(Call call) { //new call call = mOkHttpClient.newCall(request); //需要注意的是异步回调还是在子线程中,所以如果要更新ui,则记得handler call.enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { //失败 } @Override public void onResponse(Response response) { //响应 try { if (response.isSuccessful()) { //String jsonStr=response.body().string();//字符串,无编码 String jsonStr = null;//二进制字节数组 jsonStr = new String(response.body().bytes(), "UTF-8"); //InputStream inputStream=response.body().byteStream();//输入流 try { JSONObject jsonObject = new JSONObject(jsonStr); //解析数据处理 //发送数据处理 } catch (JSONException e) { e.printStackTrace(); } } else { } } catch (IOException e) { e.printStackTrace(); } } }); }
5,设置超时
/** * 设置超时 * * @param value */ public void setTimeOut(int value) { if (mOkHttpClient == null) return; mOkHttpClient.setConnectTimeout(value, TimeUnit.MILLISECONDS);//连接超时 mOkHttpClient.setReadTimeout(value, TimeUnit.MILLISECONDS);//读取超时 mOkHttpClient.setWriteTimeout(value, TimeUnit.MILLISECONDS);//写入超时 }
6,清除一个正在请求的操作
/** * 取消一个当前正在处理的Call * 使用Call.cancel()可以立即停止掉一个正在执行的call。 * 注意:如果一个线程正在写请求或者读响应,将会引发IOException。 */ public void cancelByCall() { if (call != null) { try { call.cancel(); } catch (Exception e) { e.printStackTrace(); } } }
7,清除所有的请求
/** * 清楚所有网络请求 * 你可以通过tags来同时取消多个请求。 * 当你构建一请求时,使用RequestBuilder.tag(tag)来分配一个标签。 * 之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。 * * @param isCancelAllRequests */ public void cancelAllRequests(boolean isCancelAllRequests) { if (mOkHttpClient != null) { try { if (isCancelAllRequests) { mOkHttpClient.cancel(TAG_DATA); mOkHttpClient.cancel(TAG_IMAGE); mOkHttpClient.cancel(TAG_FILE); } } catch (Exception e) { e.printStackTrace(); } } }
8,文件下载、上传带进度显示
因为okhttp自身无法显示下载进度,所以借用网上的代码实现下载进度显示。
下载进度回调
/** * 非ui线程回调文件下载进度 * 这个是非ui线程回调,不可直接操作UI */ final ProgressListener progressResponseListener = new ProgressListener() { @Override public void onProgress(long bytesRead, long contentLength, boolean done) { //长度未知的情况下回返回-1 if (contentLength != -1 && (100 * bytesRead) / contentLength >= 0) { String donePercent = (100 * bytesRead) / contentLength + "%";//上传进度 } } };
下载方法:
/** * 下载文件 * * @param url */ public void downloadFile(String url) { request = new Request.Builder() .url(url) .build(); //包装Response使其支持进度回调 ProgressHelper.addProgressResponseListener(mOkHttpClient, progressResponseListener) .newCall(request) .enqueue(new Callback() { @Override public void onFailure(Request request, IOException e) { String message; if (!NetWorkUtil.isNetworkConnected(UIAppliaction.getInstance())) { //判断是否是因为没有网络的原因 message = "网络不给给力"; } else { message = e.getMessage(); } } @Override public void onResponse(Response response) throws IOException { String message = ""; String url = response.request().url().getPath(); //获得url地址的文件后缀名 String filename = url.substring(message.indexOf("."), message.length()); InputStream inputStream = response.body().byteStream();//输入流 //通过流保存文件的工具类 if (FileUtil.insertSDCardFromInput("文件绝对路径", filename, inputStream)) message = "下载完成"; else message = "文件保存失败"; } }); }
至于其中回调的方法我这里就只贴出代码。因为是别人处理的代码,我就分享下载地址。
http://pan.baidu.com/s/1i4GIJtz
ec32
代码经测试回调进度是正常的。
这些就是基本的okhttp的使用。自己经过封装后用起来也是非常方便的。这里分享出来供大家学习。
更多相关文章
- Android(安卓)反编译apk文件得到项目文件
- Android下jni开发之ndk的使用(下载、配置、编译遇到的问题)
- Android调用相机并将照片存储到sd卡上
- Android(安卓)Adapter使用总结
- Android(安卓)JNI知识简介
- 【收集】Android(安卓)面试题
- Android(安卓)AOP(三):在Android中Javassist动态编译代码
- Android(安卓)Makefile and build system 分析
- android 资源文件的种类