OkHttp全面解析

据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。

OkHttp 处理了很多网络疑难杂症:会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败问题。

使用 OkHttp 无需重写您程序中的网络代码。OkHttp实现了几乎和java.net.HttpURLConnection一样的API。如果你用了 Apache HttpClient,则OkHttp也提供了一个对应的okhttp-apache 模块。




首先在Module的gradle文件中添加OKHTTP的依赖:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'

    
    compile 'com.squareup.okhttp3:okhttp:3.6.0'

}


1、使用OKHTTP进行GET请求:

OkHttpClient okHttpClient = new OkHttpClient();
Request.Builder builder = new Request.Builder().url(JuHeURL.getURL("红烧肉"));

//可以省略,默认是get请求
builder.method("GET", null);

final Request request = builder.build();
Call mCall = okHttpClient.newCall(request);



在主线程中执行同步的请求,需要自己手动开启线程,可以忽略,后面的例子不会再有同步的,都一样!

try {
    //同步访问网络,需要自己手动开启一个线程
    Response response=mCall.execute();
} catch (IOException e) {
    e.printStackTrace();
}


这里主要讲一下异步请求:

//异步请求
mCall.enqueue(new Callback() {
    @Override//请求错误
    public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure:" + e.toString());
    }

    @Override//请求成功
    public void onResponse(Call call, Response response) throws IOException {
        String str = null;
        if (null != response.cacheResponse()) {
            str = response.cacheResponse().toString();
            Log.i(TAG, "onResponse:-----------str" + str);
        } else {
            str = response.networkResponse().toString();
            Log.i(TAG, "onResponse:===========str:" + str);
        }
    }


Request是OkHttp中访问的请求类,Builder是辅助类。Response是OkHttp中的响应类。请求成功后的Response对象的

response.body()返回ResponseBody类的对象,该对象可以很方便的获得返回的字符串或者是流的形式(后面的异步下载文件有示范!)。


这里需要注意一下,请求成功后回调的onResponse方法中的response对象的:第一次使用response.body().string()方法的时候 
可以正确拿到数据,第二次就会报错:java.lang.IllegalStateException:    为什么会这个样子呢?这里解释一下:
因为response.body()也是挺大的,OkHttp没有把它存储在内存中,你需要的时候就去读一次,只给你了内容,没有给引用,所以一次请求只能读一次!

回到源码,我们去看看:

public final String string() throws IOException {
  BufferedSource source = source();
  try {
    Charset charset = Util.bomAwareCharset(source, charset());
    return source.readString(charset);
  } finally {
    Util.closeQuietly(source);
  }
}

看!!!!我们都知道finally中的代码肯定会调用这里执行 
Util.closeQuietly(source);~~~~

closeQuietly方法可以运用到各类可关闭的对象中

所以懂了 
就是因为在拿过之后就把资源关闭了 
所以就获取不到了,所以只能拿一次。

也算是个小坑,记录记录~~~~


当然,OKHTTP也支持我们取消一个Call:

//立即停止掉一个正在执行的call
mCall.cancel();
如果一个线程正在写请求或者读响应,将会引发 IOException 。当call没有必要的时候,使用这个api可以节约网络资源。例如当用户离开一个应用时。不管同步还是异步的call都可以取消!

你也可以通过tags来同时取消多个请求。当你构建一请求时,使用RequestBuilder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。









2、使用OKHTTP进行POST请求:

String url = "http://api.1-blog.com/biz/bizserver/article/list.do";
OkHttpClient okHttpClient = new OkHttpClient();

//很多时候我们会需要通过POST方式把键值对数据传送到服务器
RequestBody RequestBody = new FormBody.Builder()
        .add("size", "10")
        .add("platform","android")
        .add("name","bug")
        .build();

Request request = new Request.Builder().url(url).post(RequestBody).build();
Call call = okHttpClient.newCall(request);
当然,我这边的URL你测试的时候还是要换一下的哦!post请求的辅助类RequestBoby,以及他的add方法,把参数传进去!


//异步请求
call.enqueue(new Callback() {
    @Override//请求错误
    public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure: " + e.toString());
    }


    @Override//请求成功
    public void onResponse(Call call, Response response) throws IOException {
        String str = response.body().string();
        Log.i(TAG, "onResponse: " + str);
    }
});




3、异步上传文件:

//上传文件本身也是一个POST请求,首先定义上传文件类型:
MediaType maMediaType = MediaType.parse("text/x-markdown; charset=utf-8");

OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("/sdcard/wangshu.txt");
Request request = new Request.Builder()
        .url("https://api.github.com/markdown/raw")
        .post(RequestBody.create(maMediaType, file))
        .build();

//将文件上传到服务器上:
okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure: " + e.toString());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.i(TAG, "onResponse: " + response.body().string());
    }
});






4、异步上传Multipart文件:

这种情况还比较常见,当我们需要上传文件的同时还要上传其他类型的字段,实现起来很简单,这里只是举个例子,具体的应用要结合实际工作中对应的服务器:


//首先定义上传文件类型:
MediaType mediaType = MediaType.parse("image/png");

OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("title", "wangshu")
        .addFormDataPart("image", "wangshu.jpg", RequestBody.create(mediaType, new File("/sdcard/wangshu.jpg")))
        .build();

Request request = new Request.Builder()
        .header("Authorization", "Client-ID " + "...")
        .url("https://api.imgur.com/3/image")
        .post(requestBody)
        .build();

okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure: " + e.toString());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        Log.i(TAG, "onResponse: " + response.body().string());
    }
});






5、异步下载文件:

OkHttpClient okHttpClient = new OkHttpClient();
String url = "http://imgsrc.baidu.com/baike/pic/item/b58f8c5494eef01f579b09d2e4fe9925bc317d1d.jpg";
Request request = new Request.Builder().url(url).build();

okHttpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.i(TAG, "onFailure: " + e.toString());
    }

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

        InputStream inputStream = response.body().byteStream();
        FileOutputStream outputStream = null;

        try {
            outputStream = new FileOutputStream(new File("/sdcard/我的杨钰莹.jpg"));
            byte[] buBytes = new byte[2048];
            int let = 0;
            while ((let = inputStream.read(buBytes)) != -1) {
                outputStream.write(buBytes, 0, let);
            }
            outputStream.flush();
        } catch (IOException e) {
            Log.i(TAG, "onResponse: 文件下载出错了....");
            e.printStackTrace();
        }
        Log.i(TAG, "onResponse: 文件下载成功!----------------------------");

    }
});





6、设置OKHTTP的超时时间和缓存:

    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 okHttpClient=builder.build();
}

这里需要说明的就是:getExternalCacheDir()方法可以获取到 SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据

如果使用该方法,当你的应用在被用户卸载后,SDCard/Android/data/你的应用的包名/ 这个目录下的所有文件都会被删除,不会留下垃圾信息。
目录对应 设置->应用->应用详情里面的”清除缓存“选项。

	好了,这次的OKHTTP的简单使用就说到这里啦!




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值