安卓中如何取得okhttp返回的responsebody string.body().string()中我想要的值

6657人阅读
android(55)
支持 SPDY ,共享同一个 Socket 来处理同一个服务器的所有请求
如果 SPDY 不可用,则通过连接池来减少请求延时
无缝的支持GZIP来减少数据流量
缓存响应数据来减少重复的网络请求
& OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。
& OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。
一、测试使用我们的OKHttp第三方库
1.第一步我们需要去创建一个&OKHttpClient&对象
OkHttpClient okHttpClient = new OkHttpClient();
2.下一步我们还需要一个&Request&对象,她可以已如下方式被创建
Request request = new Request.Builder()
.url(requestUrl)
requestUrl是一个字符串变量代表这个URL是为了JSON请求(The&requestUrl&is a String variable representing the Url for the JSON request.)&
在这个测试中,我们将会使用如下的URl:/api/v1/random?format=json
3.再下一步我们需要实例化一个&Call&对象
= okHttpClient.newCall(request);
Call对象会取走我们的&okHttpClient对象 和 我们的&request对象。
4.在实例化Call对象后,我们现在可以 Execute(执行)她。Executing一个Call后将会返回一个 Response,并且会抛出一个 IOException的异常,这就是为什么们会用一个try,catch块包裹她。
Response response = call.execute();
}catch (IOException e){
e.printStackTrace();
5.执行完我们的Call后,我们需要通过使用&response.isSuccessful()来检查Call对象是否执行成功,
通过response.isSuccessful()的返回值为true或者是false来判断。
这我们仅仅是一个测试,如果Call成功的话,我们将会通过Log来打印我们的response。
Response response = call.execute();
if(response.isSuccessful()){
//The call was successful.print it to the log
Log.v(&OKHttp&,response.body().string());
}catch(IOException e){
e.printStackTrace();
6.测试Code!
这是新手一个常见的错误。在Android中不允许任何网络的交互在主线程中进行。It disallows it to force developers to use asynchronous callbacks.(能力有限这句话不敢强译)。但是现在,我们的代码看起来看起来十分的号好!下面我们来看看如何修复这个问题。
7.Fix issue
为了修补这个问题,我们只需要让我们的Call执行在非主线程内,所以利用一个&asynchronous callback(异步的callBack)。
让我们call异步的方法是通过调用我们Call对象的&enqueue()方法。
call.enqueue(new Callback()) {
public void onFailure( Request request, IOException e ) {
public void OnResponse( Response response) throws IOException {
if(response.isSuccessful()){
//The call was successful. print it to the log
log.v(&OKHttp&,response.body.string());
}catch (IOException e) {
e.printStackTrace();
8.在我们再次执行我们的code之前,我们还需要再改一改。如果我们想要现在执行她,我们可能还会接收到错误的提示,因为我们应用的程序没有得到相应的相应的网络权限。所以我们需要再AndroidManifest.xml中添加应用权限。
&uses-permission android:name=&android.permission.INTERNET&/&
9.当我们执行完code后,我们将接受到如下的log输出:
10.This means, we are now able to execute asynchronous network calls and use the data inside the callback method, when it is ready!
onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()
看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等
二、请求方法介绍
1、HTTP请求方法
同步GET请求
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&/helloworld.txt&)
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&Headers&responseHeaders&=&response.headers();
&&&&for&(int&i&=&0;&i&&&responseHeaders.size();&i++)&{
&&&&&&&&System.out.println(responseHeaders.name(i)&+&&:&&&+&responseHeaders.value(i));
&&&&System.out.println(response.body().string());
& Response类的string()方法会把文档的所有内容加载到内存,适用于小文档,对应大于1M的文档,应 & 使用流()的方式获取。
response.body().byteStream()
异步GET请求
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&/helloworld.txt&)
&&&&&&&&&&&&.build();
&&&&client.newCall(request).enqueue(new&Callback()&{
&&&&&&&&@Override
&&&&&&&&public&void&onFailure(Request&request,&IOException&e)&{
&&&&&&&&&&&&e.printStackTrace();
&&&&&&&&@Override
&&&&&&&&public&void&onResponse(Response&response)&throws&IOException&{
&&&&&&&&&&&&if&(!response.isSuccessful())&{
&&&&&&&&&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&&&&&&&&&}
&&&&&&&&&&&&Headers&responseHeaders&=&response.headers();
&&&&&&&&&&&&for&(int&i&=&0;&i&&&responseHeaders.size();&i++)&{
&&&&&&&&&&&&&&&&System.out.println(responseHeaders.name(i)&+&&:&&&+&responseHeaders.value(i));
&&&&&&&&&&&&}
&&&&&&&&&&&&System.out.println(response.body().string());
& 读取响应会阻塞当前线程,所以发起请求是在主线程,回调的内容在非主线程中。
POST方式提交字符串
private&static&final&MediaType&MEDIA_TYPE_MARKDOWN
&&&&&&&&=&MediaType.parse(&text/x-&charset=utf-8&);
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&String&postBody&=&&&
&&&&&&&&&&&&+&&Releases\n&
&&&&&&&&&&&&+&&--------\n&
&&&&&&&&&&&&+&&\n&
&&&&&&&&&&&&+&&&*&_1.0_&May&6,&2013\n&
&&&&&&&&&&&&+&&&*&_1.1_&June&15,&2013\n&
&&&&&&&&&&&&+&&&*&_1.2_&August&11,&2013\n&;
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&/markdown/raw&)
&&&&&&&&&&&&.post(RequestBody.create(MEDIA_TYPE_MARKDOWN,&postBody))
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())&
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&System.out.println(response.body().string());
& 因为整个请求体都在内存中,应避免提交1M以上的文件。
POST方式提交流
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&RequestBody&requestBody&=&new&RequestBody()&{
&&&&&&&&@Override
&&&&&&&&public&MediaType&contentType()&{
&&&&&&&&&&&&return&MEDIA_TYPE_MARKDOWN;
&&&&&&&&@Override
&&&&&&&&public&void&writeTo(BufferedSink&sink)&throws&IOException&{
&&&&&&&&&&&&sink.writeUtf8(&Numbers\n&);
&&&&&&&&&&&&sink.writeUtf8(&-------\n&);
&&&&&&&&&&&&for&(int&i&=&2;&i&&=&997;&i++)&{
&&&&&&&&&&&&&&&&sink.writeUtf8(String.format(&&*&%s&=&%s\n&,&i,&factor(i)));
&&&&&&&&&&&&}
&&&&&&&&private&String&factor(int&n)&{
&&&&&&&&&&&&for&(int&i&=&2;&i&&&n;&i++)&{
&&&&&&&&&&&&&&&&int&x&=&n&/&i;
&&&&&&&&&&&&&&&&if&(x&*&i&==&n)&return&factor(x)&+&&&×&&&+&i;
&&&&&&&&&&&&}
&&&&&&&&&&&&return&Integer.toString(n);
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&/markdown/raw&)
&&&&&&&&&&&&.post(requestBody)
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())&
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&System.out.println(response.body().string());
& 使用Okio框架以流的形式将内容写入,这种方式不会出现内存溢出问题。
POST方式提交文件
public&static&final&MediaType&MEDIA_TYPE_MARKDOWN
&&&&&&&&=&MediaType.parse(&text/x-&charset=utf-8&);
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&File&file&=&new&File(&README.md&);
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&/markdown/raw&)
&&&&&&&&&&&&.post(RequestBody.create(MEDIA_TYPE_MARKDOWN,&file))
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())&
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&System.out.println(response.body().string());
POST方式提交表单
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&RequestBody&formBody&=&new&FormEncodingBuilder()
&&&&&&&&&&&&.add(&search&,&&Jurassic&Park&)
&&&&&&&&&&&&.build();
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.url(&https://en.wikipedia.org/w/index.php&)
&&&&&&&&&&&&.post(formBody)
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())&
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&System.out.println(response.body().string());
& 表单的每个Names-Values都进行了URL编码。如果服务器端接口未进行URL编码,可定制个 &FormBuilder。
文件上传(兼容html文件上传)
private&static&final&String&IMGUR_CLIENT_ID&=&&...&;
private&static&final&MediaType&MEDIA_TYPE_PNG&=&MediaType.parse(&image/png&);
private&final&OkHttpClient&client&=&new&OkHttpClient();
public&void&run()&throws&Exception&{
&&&&//&Use&the&imgur&image&upload&API&as&documented&at&/endpoints/image
&&&&RequestBody&requestBody&=&new&MultipartBuilder()
&&&&&&&&&&&&.type(MultipartBuilder.FORM)
&&&&&&&&&&&&.addPart(
&&&&&&&&&&&&&&&&&&&&Headers.of(&Content-Disposition&,&&form-&name=\&title\&&),
&&&&&&&&&&&&&&&&&&&&RequestBody.create(null,&&Square&Logo&))
&&&&&&&&&&&&.addPart(
&&&&&&&&&&&&&&&&&&&&Headers.of(&Content-Disposition&,&&form-&name=\&image\&&),
&&&&&&&&&&&&&&&&&&&&RequestBody.create(MEDIA_TYPE_PNG,&new&File(&website/static/logo-square.png&)))
&&&&&&&&&&&&.build();
&&&&Request&request&=&new&Request.Builder()
&&&&&&&&&&&&.header(&Authorization&,&&Client-ID&&&+&IMGUR_CLIENT_ID)
&&&&&&&&&&&&.url(&/3/image&)
&&&&&&&&&&&&.post(requestBody)
&&&&&&&&&&&&.build();
&&&&Response&response&=&client.newCall(request).execute();
&&&&if&(!response.isSuccessful())&
&&&&&&&&throw&new&IOException(&Unexpected&code&&&+&response);
&&&&System.out.println(response.body().string());
& 原文地址:
1、/ryan-ys/p/4777450.html
2、/info-detail-511504.html
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:37556次
排名:千里之外
原创:46篇
转载:25篇
(1)(3)(6)(14)(2)(1)(1)(7)(9)(18)(5)(1)(3)官方文档:/square/okhttp/wiki/Recipes/square/okhttp以下只考虑小数据量请求,比如请求rest json API相关注意点1. okhttp3比较多的地方使用了builder模式,OkHttpClient、Request、FormBody等都可以通过&Class&.Builder()获取相应的Builder,进而进行相关的配置。2. ResponseBody用完了要及时关闭Each response body is backed by a limited resource like a socket (live network responses) or an open file (for cached responses). Failing to close the response body will leak these resources and may ultimately cause the application to slow down or crash. Close the response body by calling either&close(),&byteStream().close(), or&reader().close(). The&bytes()&and&string()&methods both close the response body automatically.相关请求代码首先创建一个自定义的Response(这个个人喜好)public static class Response {
}Get请求/**
* http get 请求
* @param url
Response请求结果实例,通过response.code==200判断是否有效
public static Response httpGet(String url) {
Response response = new Response();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
proceedRequest(client, request, response);
此处的通用处理请求函数
上一篇: 下一篇:114网址导航你的位置: >
> Android OkHttp完全解析 是时候来了解OkHttp了
最近在群里听到各种讨论okhttp的话题,可见okhttp的口碑相当好了。再加上Google貌似在6.0版本里面删除了HttpClient相关API,对于这个行为不做评价。为了更好的在应对网络访问,学习下okhttp还是蛮必要的,本篇博客首先介绍okhttp的简单使用,主要包含:
一般的get请求
一般的post请求
基于Http的文件上传
支持请求回调,直接返回对象、对象集合
支持session的保持
最后会对上述几个功能进行封装,完整的封装类的地址见:
使用前,对于Android Studio的用户,可以选择添加:
compile 'com.squareup.okhttp:okhttp:2.4.0'
或者Eclipse的用户,可以下载最新的jar ,添加依赖就可以用了。
注意:okhttp内部依赖okio,别忘了同时导入okio:
gradle: compile 'com.squareup.okio:okio:1.5.0'
最新的jar地址:
二、使用教程
(一)Http Get
对了网络加载库,那么最常见的肯定就是http get请求了,比如获取一个网页的内容。
//创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
.url(&/hongyangAndroid&)
//new call
Call call = mOkHttpClient.newCall(request);
//请求加入调度
call.enqueue(new Callback()
public void onFailure(Request request, IOException e)
public void onResponse(final Response response) throws IOException
//String htmlStr =
response.body().string();
以上就是发送一个get请求的步骤,首先构造一个Request对象,参数最起码有个url,当然你可以通过Request.Builder设置更多的参数比如:header、method等。
然后通过request的对象去构造得到一个Call对象,类似于将你的请求封装成了任务,既然是任务,就会有execute()和cancel()等方法。
最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。
看到这,你会发现,整体的写法还是比较长的,所以封装肯定是要做的,不然每个请求这么写,得累死。
ok,需要注意几点:
onResponse回调的参数是response,一般情况下,比如我们希望获得返回的字符串,可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()看到这,你可能会奇怪,竟然还能拿到返回的inputStream,看到这个最起码能意识到一点,这里支持大文件下载,有inputStream我们就可以通过IO的方式写文件。不过也说明一个问题,这个onResponse执行的线程并不是UI线程。的确是的,如果你希望操作控件,还是需要使用handler等,例如:
public void onResponse(final Response response) throws IOException
final String res = response.body().string();
runOnUiThread(new Runnable()
public void run()
mTv.setText(res);
我们这里是异步的方式去执行,当然也支持阻塞的方式,上面我们也说了Call有一个execute()方法,你也可以直接调用call.execute()通过返回一个Response。
(二) Http Post 携带参数
看来上面的简单的get请求,基本上整个的用法也就掌握了,比如post携带参数,也仅仅是Request的构造的不同。
Request request = buildMultipartFormRequest(
url, new File[]{file}, new String[]{fileKey}, null);
FormEncodingBuilder builder = new FormEncodingBuilder();
builder.add(&username&,&张鸿洋&);
Request request = new Request.Builder()
.post(builder.build())
mOkHttpClient.newCall(request).enqueue(new Callback(){});
大家都清楚,post的时候,参数是包含在请求体中的;所以我们通过FormEncodingBuilder。添加多个String键值对,然后去构造RequestBody,最后完成我们Request的构造。
后面的就和上面一样了。
(三)基于Http的文件上传
接下来我们在介绍一个可以构造RequestBody的Builder,叫做MultipartBuilder。当我们需要做类似于表单上传的时候,就可以使用它来构造我们的requestBody。
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- name=\&username\&&),
RequestBody.create(null, &张鸿洋&))
.addPart(Headers.of(
&Content-Disposition&,
&form- name=\&mFile\&;
filename=\&wjd.mp4\&&), fileBody)
Request request = new Request.Builder()
.url(&http://192.168.1.103:8080/okHttpServer/fileUpload&)
.post(requestBody)
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback()
上述代码向服务器传递了一个键值对username:张鸿洋和一个文件。我们通过MultipartBuilder的addPart方法可以添加键值对或者文件。
其实类似于我们拼接模拟浏览器行为的方式,如果你对这块不了解,可以参考:
ok,对于我们最开始的目录还剩下图片下载,文件下载;这两个一个是通过回调的Response拿到byte[]然后decode成图片;文件下载,就是拿到inputStream做写文件操作,我们这里就不赘述了。
关于用法,也可以参考
接下来我们主要看如何封装上述的代码。
由于按照上述的代码,写多个请求肯定包含大量的重复代码,所以我希望封装后的代码调用是这样的:
(一)使用
一般的get请求
OkHttpClientManager.getAsyn(&&, new OkHttpClientManager.ResultCallback&String&()
public void onError(Request request, Exception e)
e.printStackTrace();
public void onResponse(String u)
mTv.setText(u);//注意这里是UI线程
对于一般的请求,我们希望给个url,然后CallBack里面直接操作控件。
文件上传且携带参数我们希望提供一个方法,传入url,params,file,callback即可。
OkHttpClientManager.postAsyn(&http://192.168.1.103:8080/okHttpServer/fileUpload&,//
new OkHttpClientManager.ResultCallback&String&()
public void onError(Request request, IOException e)
e.printStackTrace();
public void onResponse(String result)
&mFile&,//
new OkHttpClientManager.Param[]{
new OkHttpClientManager.Param(&username&, &zhy&),
new OkHttpClientManager.Param(&password&, &123&)}
键值对没什么说的,参数3为file,参数4为file对应的name,这个name不是文件的名字;
对应于http中的
&input type="file" name="mFile" &
对应的是name后面的值,即mFile.
文件下载对于文件下载,提供url,目标dir,callback即可。
OkHttpClientManager.downloadAsyn(
&http://192.168.1.103:8080/okHttpServer/files/messenger_01.png&,
Environment.getExternalStorageDirectory().getAbsolutePath(),
new OkHttpClientManager.ResultCallback&String&()
public void onError(Request request, IOException e)
public void onResponse(String response)
//文件下载成功,这里回调的reponse为文件的absolutePath
展示图片展示图片,我们希望提供一个url和一个imageview,如果下载成功,直接帮我们设置上即可。
OkHttpClientManager.displayImage(mImageView,
"http://images.csdn.net/.jpg");
内部会自动根据imageview的大小自动对图片进行合适的压缩。虽然,这里可能不适合一次性加载大量图片的场景,但是对于app中偶尔有几个图片的加载,还是可用的。
四、整合Gson
很多人提出项目中使用时,服务端返回的是Json字符串,希望客户端回调可以直接拿到对象,于是整合进入了Gson,完善该功能。
(一)直接回调对象
例如现在有个User实体类:
package com.zhy.utils.http.
public class User {
public User() {
// TODO Auto-generated constructor stub
public User(String username, String password) {
this.username =
this.password =
public String toString()
return &User{& +
&username='& + username + '\'' +
&, password='& + password + '\'' +
服务端返回:
{&username&:&zhy&,&password&:&123&}
客户端可以如下方式调用:
OkHttpClientManager.getAsyn(&http://192.168.56.1:8080/okHttpServer/user!getUser&,
new OkHttpClientManager.ResultCallback&User&()
public void onError(Request request, Exception e)
e.printStackTrace();
public void onResponse(User user)
mTv.setText(u.toString());//UI线程
我们传入泛型User,在onResponse里面直接回调User对象。
这里特别要注意的事,如果在json字符串-&实体对象过程中发生错误,程序不会崩溃,onError方法会被回调。
注意:这里做了少许的更新,接口命名从StringCallback修改为ResultCallback。接口中的onFailure方法修改为onError。
(二) 回调对象集合
依然是上述的User类,服务端返回
[{&username&:&zhy&,&password&:&123&},{&username&:&lmj&,&password&:&12345&}]
则客户端可以如下调用:
OkHttpClientManager.getAsyn(&http://192.168.56.1:8080/okHttpServer/user!getUsers&,
new OkHttpClientManager.ResultCallback&List&User&&()
public void onError(Request request, Exception e)
e.printStackTrace();
public void onResponse(List&User& us)
Log.e(&TAG&, us.size() + &&);
mTv.setText(us.get(1).toString());
唯一的区别,就是泛型变为List&User& ,ok , 如果发现bug或者有任何意见欢迎留言。
ok,基本介绍完了,对于封装的代码其实也很简单,我就直接贴出来了,因为也没什么好介绍的,如果你看完上面的用法,肯定可以看懂:
package com.zhy.utils.http.
import android.graphics.B
import android.graphics.BitmapF
import android.os.H
import android.os.L
import android.widget.ImageV
import com.google.gson.G
import com.google.gson.internal.$Gson$T
import com.squareup.okhttp.C
import com.squareup.okhttp.C
import com.squareup.okhttp.FormEncodingB
import com.squareup.okhttp.H
import com.squareup.okhttp.MediaT
import com.squareup.okhttp.MultipartB
import com.squareup.okhttp.OkHttpC
import com.squareup.okhttp.R
import com.squareup.okhttp.RequestB
import com.squareup.okhttp.R
import java.io.F
import java.io.FileOutputS
import java.io.IOE
import java.io.InputS
import java.lang.reflect.ParameterizedT
import java.lang.reflect.T
import java.net.CookieM
import java.net.CookieP
import java.net.FileNameM
import java.net.URLC
import java.util.HashM
import java.util.M
import java.util.S
* Created by zhy on 15/8/17.
public class OkHttpClientManager
private static OkHttpClientManager mI
private OkHttpClient mOkHttpC
private Handler mD
private Gson mG
private static final String TAG = &OkHttpClientManager&;
private OkHttpClientManager()
mOkHttpClient = new OkHttpClient();
//cookie enabled
mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
public static OkHttpClientManager getInstance()
if (mInstance == null)
synchronized (OkHttpClientManager.class)
if (mInstance == null)
mInstance = new OkHttpClientManager();
* 同步的Get请求
* @param url
* @return Response
private Response _getAsyn(String url) throws IOException
final Request request = new Request.Builder()
Call call = mOkHttpClient.newCall(request);
Response execute = call.execute();
* 同步的Get请求
* @param url
* @return 字符串
private String _getAsString(String url) throws IOException
Response execute = _getAsyn(url);
return execute.body().string();
* 异步的get请求
* @param url
* @param callback
private void _getAsyn(String url, final ResultCallback callback)
final Request request = new Request.Builder()
deliveryResult(callback, request);
* 同步的Post请求
* @param url
* @param params post的参数
private Response _post(String url, Param... params) throws IOException
Request request = buildPostRequest(url, params);
Response response = mOkHttpClient.newCall(request).execute();
* 同步的Post请求
* @param url
* @param params post的参数
* @return 字符串
private String _postAsString(String url, Param... params) throws IOException
Response response = _post(url, params);
return response.body().string();
* 异步的post请求
* @param url
* @param callback
* @param params
private void _postAsyn(String url, final ResultCallback callback, Param... params)
Request request = buildPostRequest(url, params);
deliveryResult(callback, request);
* 异步的post请求
* @param url
* @param callback
* @param params
private void _postAsyn(String url, final ResultCallback callback, Map&String, String& params)
Param[] paramsArr = map2Params(params);
Request request = buildPostRequest(url, paramsArr);
deliveryResult(callback, request);
* 同步基于post的文件上传
* @param params
private Response _post(String url, File[] files, String[] fileKeys, Param... params) throws IOException
Request request = buildMultipartFormRequest(url, files, fileKeys, params);
return mOkHttpClient.newCall(request).execute();
private Response _post(String url, File file, String fileKey) throws IOException
Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
return mOkHttpClient.newCall(request).execute();
private Response _post(String url, File file, String fileKey, Param... params) throws IOException
Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
return mOkHttpClient.newCall(request).execute();
* 异步基于post的文件上传
* @param url
* @param callback
* @param files
* @param fileKeys
* @throws IOException
private void _postAsyn(String url, ResultCallback callback, File[] files, String[] fileKeys, Param... params) throws IOException
Request request = buildMultipartFormRequest(url, files, fileKeys, params);
deliveryResult(callback, request);
* 异步基于post的文件上传,单文件不带参数上传
* @param url
* @param callback
* @param file
* @param fileKey
* @throws IOException
private void _postAsyn(String url, ResultCallback callback, File file, String fileKey) throws IOException
Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, null);
deliveryResult(callback, request);
* 异步基于post的文件上传,单文件且携带其他form参数上传
* @param url
* @param callback
* @param file
* @param fileKey
* @param params
* @throws IOException
private void _postAsyn(String url, ResultCallback callback, File file, String fileKey, Param... params) throws IOException
Request request = buildMultipartFormRequest(url, new File[]{file}, new String[]{fileKey}, params);
deliveryResult(callback, request);
* 异步下载文件
* @param url
* @param destFileDir 本地文件存储的文件夹
* @param callback
private void _downloadAsyn(final String url, final String destFileDir, final ResultCallback callback)
final Request request = new Request.Builder()
final Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback()
public void onFailure(final Request request, final IOException e)
sendFailedStringCallback(request, e, callback);
public void onResponse(Response response)
InputStream is =
byte[] buf = new byte[2048];
int len = 0;
FileOutputStream fos =
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();
//如果下载文件成功,第一个参数为文件的绝对路径
sendSuccessResultCallback(file.getAbsolutePath(), callback);
} catch (IOException e)
sendFailedStringCallback(response.request(), e, callback);
if (is != null) is.close();
} catch (IOException e)
if (fos != null) fos.close();
} catch (IOException e)
private String getFileName(String path)
int separatorIndex = path.lastIndexOf(&/&);
return (separatorIndex & 0) ? path : path.substring(separatorIndex + 1, path.length());
* 加载图片
* @param view
* @param url
* @throws IOException
private void _displayImage(final ImageView view, final String url, final int errorResId)
final Request request = new Request.Builder()
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback()
public void onFailure(Request request, IOException e)
setErrorResId(view, errorResId);
public void onResponse(Response response)
InputStream is =
is = response.body().byteStream();
ImageUtils.ImageSize actualImageSize = ImageUtils.getImageSize(is);
ImageUtils.ImageSize imageViewSize = ImageUtils.getImageViewSize(view);
int inSampleSize = ImageUtils.calculateInSampleSize(actualImageSize, imageViewSize);
is.reset();
} catch (IOException e)
response = _getAsyn(url);
is = response.body().byteStream();
BitmapFactory.Options ops = new BitmapFactory.Options();
ops.inJustDecodeBounds =
ops.inSampleSize = inSampleS
final Bitmap bm = BitmapFactory.decodeStream(is, null, ops);
mDelivery.post(new Runnable()
public void run()
view.setImageBitmap(bm);
} catch (Exception e)
setErrorResId(view, errorResId);
if (is != null) try
is.close();
} catch (IOException e)
e.printStackTrace();
private void setErrorResId(final ImageView view, final int errorResId)
mDelivery.post(new Runnable()
public void run()
view.setImageResource(errorResId);
//*************对外公布的方法************
public static Response getAsyn(String url) throws IOException
return getInstance()._getAsyn(url);
public static String getAsString(String url) throws IOException
return getInstance()._getAsString(url);
public static void getAsyn(String url, ResultCallback callback)
getInstance()._getAsyn(url, callback);
public static Response post(String url, Param... params) throws IOException
return getInstance()._post(url, params);
public static String postAsString(String url, Param... params) throws IOException
return getInstance()._postAsString(url, params);
public static void postAsyn(String url, final ResultCallback callback, Param... params)
getInstance()._postAsyn(url, callback, params);
public static void postAsyn(String url, final ResultCallback callback, Map&String, String& params)
getInstance()._postAsyn(url, callback, params);
public static Response post(String url, File[] files, String[] fileKeys, Param... params) throws IOException
return getInstance()._post(url, files, fileKeys, params);
public static Response post(String url, File file, String fileKey) throws IOException
return getInstance()._post(url, file, fileKey);
public static Response post(String url, File file, String fileKey, Param... params) throws IOException
return getInstance()._post(url, file, fileKey, params);
public static void postAsyn(String url, ResultCallback callback, File[] files, String[] fileKeys, Param... params) throws IOException
getInstance()._postAsyn(url, callback, files, fileKeys, params);
public static void postAsyn(String url, ResultCallback callback, File file, String fileKey) throws IOException
getInstance()._postAsyn(url, callback, file, fileKey);
public static void postAsyn(String url, ResultCallback callback, File file, String fileKey, Param... params) throws IOException
getInstance()._postAsyn(url, callback, file, fileKey, params);
public static void displayImage(final ImageView view, String url, int errorResId) throws IOException
getInstance()._displayImage(view, url, errorResId);
public static void displayImage(final ImageView view, String url)
getInstance()._displayImage(view, url, -1);
public static void downloadAsyn(String url, String destDir, ResultCallback callback)
getInstance()._downloadAsyn(url, destDir, callback);
//****************************
private Request buildMultipartFormRequest(String url, File[] files,
String[] fileKeys, Param[] params)
params = validateParam(params);
MultipartBuilder builder = new MultipartBuilder()
.type(MultipartBuilder.FORM);
for (Param param : params)
builder.addPart(Headers.of(&Content-Disposition&, &form- name=\&& + param.key + &\&&),
RequestBody.create(null, param.value));
if (files != null)
RequestBody fileBody =
for (int i = 0; i & files. i++)
File file = files[i];
String fileName = file.getName();
fileBody = RequestBody.create(MediaType.parse(guessMimeType(fileName)), file);
//TODO 根据文件名设置contentType
builder.addPart(Headers.of(&Content-Disposition&,
&form- name=\&& + fileKeys[i] + &\&; filename=\&& + fileName + &\&&),
fileBody);
RequestBody requestBody = builder.build();
return new Request.Builder()
.post(requestBody)
private String guessMimeType(String path)
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null)
contentTypeFor = &application/octet-stream&;
return contentTypeF
private Param[] validateParam(Param[] params)
if (params == null)
return new Param[0];
private Param[] map2Params(Map&String, String& params)
if (params == null) return new Param[0];
int size = params.size();
Param[] res = new Param[size];
Set&Map.Entry&String, String&& entries = params.entrySet();
int i = 0;
for (Map.Entry&String, String& entry : entries)
res[i++] = new Param(entry.getKey(), entry.getValue());
private static final String SESSION_KEY = &Set-Cookie&;
private static final String mSessionKey = &JSESSIONID&;
private Map&String, String& mSessions = new HashMap&String, String&();
private void deliveryResult(final ResultCallback callback, Request request)
mOkHttpClient.newCall(request).enqueue(new Callback()
public void onFailure(final Request request, final IOException e)
sendFailedStringCallback(request, e, callback);
public void onResponse(final Response response)
final String string = response.body().string();
if (callback.mType == String.class)
sendSuccessResultCallback(string, callback);
Object o = mGson.fromJson(string, callback.mType);
sendSuccessResultCallback(o, callback);
} catch (IOException e)
sendFailedStringCallback(response.request(), e, callback);
} catch (com.google.gson.JsonParseException e)//Json解析的错误
sendFailedStringCallback(response.request(), e, callback);
private void sendFailedStringCallback(final Request request, final Exception e, final ResultCallback callback)
mDelivery.post(new Runnable()
public void run()
if (callback != null)
callback.onError(request, e);
private void sendSuccessResultCallback(final Object object, final ResultCallback callback)
mDelivery.post(new Runnable()
public void run()
if (callback != null)
callback.onResponse(object);
private Request buildPostRequest(String url, Param[] params)
if (params == null)
params = new Param[0];
FormEncodingBuilder builder = new FormEncodingBuilder();
for (Param param : params)
builder.add(param.key, param.value);
RequestBody requestBody = builder.build();
return new Request.Builder()
.post(requestBody)
public static abstract class ResultCallback&T&
public ResultCallback()
mType = getSuperclassTypeParameter(getClass());
static Type getSuperclassTypeParameter(Class&?& subclass)
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class)
throw new RuntimeException(&Missing type parameter.&);
ParameterizedType parameterized = (ParameterizedType)
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
public abstract void onError(Request request, Exception e);
public abstract void onResponse(T response);
public static class Param
public Param()
public Param(String key, String value)
this.key =
this.value =
源码地址,大家可以自己下载查看。
转载请标明出处:
转载请注明: &
与本文相关的文章

我要回帖

更多关于 okhttp response 乱码 的文章

 

随机推荐