网络请求框架:okhttp+ion+volley

本文详细介绍了OkHttp网络库的特点及使用方法,包括同步与异步请求、响应处理、超时配置、缓存机制等内容,并提供了丰富的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原理:
① 底层都是走HttpUrlConnection

步骤:
① 添加网络权限。
② 验证url。
③ 添加依赖 compile : studio 看到 compile 指令 去仓库下载jar包&源代码 并绑定。
④ 编写请求。 a、初始化框架  b、发送   c、接收 回调。


volley


Volley的使用
无文件上传下载 新闻 支付
介绍 
谷歌开源的,专注于处理高频率的数据比较小的请求
优点 : 高并发&小数据量的请求。例如 : 股票交易软件。阿里支付。微信支付。
缺点: 处理文件效率低。
内部仍然是使用的HttpURLConnection和HttpClient进行网络请求的,
只是对于不同的Android版本进行了响应的切换,2.3之前使用的HttpClient,
2.3之后使用的是HttpURLConnection
支持取消请求
具有网络请求和图片加载的功能

使用:
Volley 框架本身。
Request 提交给服务器的请求数据。
Response  服务器返回给客户端的数据。

Volley封装
     
  1. public class HttpUtil {
  2. public static void request(Context context, String url,final Map<String, String> map,CallBack callBack) {
  3. //参1.请求方式 METHOD.GET
  4. //参2.地址
  5. //参3.正确
  6. //参4.错误
  7. Request request = new StringRequest(map==null?Request.Method.GET:Request.Method.POST, url, callBack, callBack){
  8. @Override
  9. protected Map<String, String> getParams() throws AuthFailureError {
  10. return map;
  11. }
  12. };
  13. //Ctrl+H 继承关系 StringRequest:返回为字符串的请求json/xml
  14. //Ctrl+P 查看方法参数
  15. //4.编写请求 a.初始化框架 b.发送 c.接收 回调
  16. //Queue有序的集合,先后顺利.
  17. Volley.newRequestQueue(context).add(request);
  18. }
  19. public static class CallBack implements Response.Listener<String>, Response.ErrorListener {
  20. @Override
  21. public void onErrorResponse(VolleyError error) {
  22. error.printStackTrace();
  23. //打印错误信息
  24. }
  25. @Override
  26. public void onResponse(String response) {
  27. //什么也不做
  28. }
  29. }
  30. }

使用封装类
     
  1. public void request(View view) {
  2. // 2.查看url接口
  3. // 3.依赖compile:studio看到compile指令 去仓库下载jar&源代码 绑定。
  4. HttpUtil.CallBack callback = new HttpUtil.CallBack(){
  5. @Override
  6. public void onResponse(String response) {
  7. super.onResponse(response);
  8. Toast.makeText(MainActivity.this, response, Toast.LENGTH_SHORT).show();
  9. }
  10. };
  11. // HttpUtil.request(this, ApiUrls.HELLO, null,callback);
  12. // 1.username=itheima
  13. // 2.pwd=1
  14. HashMap<String,String> map=new HashMap<>();
  15. map.put("username","itheima");
  16. map.put("pwd","1");
  17. HttpUtil.request(this, ApiUrls.LOGIN, map,callback);
  18. }


添加依赖
 compile 'com.android.volley:volley:1.0.0'

ion

Android Asynchronous Networking and Image Loading 
具体使用,学习github官方介绍。        
#Ion是什么?
ION:http库 支持线程。
功能比较全  get/post 文件上传 文件下载。
底层Socket
使用CallBack来接收服务端返回数据
Fluent API  Ion.with(this).load(url)

Ion:ion框架的核心类
with关联上下文
load加载连接对应的数据
asString:将Stream换成String字符串
setCallback设置回调 在on方法里处理业务逻辑
setBodyParameter纯文本  post请求

文件上传
setMultipartParameter
setMultipartFile

文件下载
progress添加一个进度相关的回调对象
ProgressCallback进度回调对象 【on都是运行子线程】
.write文件保存位置


okHttp


① 实现缓存的封装
资源引用:

okHttp的异步请求callback.onSuccess()   callback.onFailed()执行在非UI线程。

   
  1. compile 'com.squareup.okhttp3:okhttp:3.5.0'
已经包含okHttp+okio这两个包。

POST提交Json数据
    
  1. public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
  2. OkHttpClient client = new OkHttpClient();
  3. String post(String url, String json) throws IOException {
  4. RequestBody body = RequestBody.create(JSON, json);
  5. Request request = new Request.Builder()
  6. .url(url)
  7. .post(body)
  8. .build();
  9. Response response = client.newCall(request).execute();
  10. f (response.isSuccessful()) {
  11. return response.body().string();
  12. } else {
  13. throw new IOException("Unexpected code " + response);
  14. }
  15. }
POST提交键值对
      
  1. OkHttpClient client = new OkHttpClient();
  2. String post(String url, String json) throws IOException {
  3. RequestBody formBody = new FormEncodingBuilder() //form 表单。
  4. .add("platform", "android")
  5. .add("name", "bug")
  6. .add("subject", "XXXXXXXXXXXXXXX")
  7. .build();
  8. Request request = new Request.Builder()
  9. .url(url)
  10. .post(body)
  11. .build();
  12. Response response = client.newCall(request).execute();
  13. if (response.isSuccessful()) {
  14. return response.body().string();
  15. } else {
  16. throw new IOException("Unexpected code " + response);
  17. }
  18. }

Post方式提交String

        
  1. public static final MediaType MEDIA_TYPE_MARKDOWN
  2. = MediaType.parse("text/x-markdown; charset=utf-8");
  3. private final OkHttpClient client = new OkHttpClient();
  4. public void run() throws Exception {
  5. String postBody = ""
  6. + "Releases\n"
  7. + "--------\n"
  8. + "\n"
  9. + " * _1.0_ May 6, 2013\n"
  10. + " * _1.1_ June 15, 2013\n"
  11. + " * _1.2_ August 11, 2013\n";
  12. Request request = new Request.Builder()
  13. .url("https://api.github.com/markdown/raw")
  14. .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
  15. .build();
  16. Response response = client.newCall(request).execute();
  17. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  18. System.out.println(response.body().string());
  19. }

Post方式提交流

以流的方式POST提交请求体。请求体的内容由流写入产生。这个例子是流直接写入 Okio的BufferedSink。你的程序可能会使用 OutputStream,你可以使用 BufferedSink.outputStream()来获取。
         
  1. public static final MediaType MEDIA_TYPE_MARKDOWN
  2. = MediaType.parse("text/x-markdown; charset=utf-8");
  3. private final OkHttpClient client = new OkHttpClient();
  4. public void run() throws Exception {
  5. RequestBody requestBody = new RequestBody() {
  6. @Override public MediaType contentType() {
  7. return MEDIA_TYPE_MARKDOWN;
  8. }
  9. @Override public void writeTo(BufferedSink sink) throws IOException {
  10. sink.writeUtf8("Numbers\n");
  11. sink.writeUtf8("-------\n");
  12. for (int i = 2; i <= 997; i++) {
  13. sink.writeUtf8(String.format(" * %s = %s\n", i, factor(i)));
  14. }
  15. }
  16. private String factor(int n) {
  17. for (int i = 2; i < n; i++) {
  18. int x = n / i;
  19. if (x * i == n) return factor(x) + " × " + i;
  20. }
  21. return Integer.toString(n);
  22. }
  23. };
  24. Request request = new Request.Builder()
  25. .url("https://api.github.com/markdown/raw")
  26. .post(requestBody)
  27. .build();
  28. Response response = client.newCall(request).execute();
  29. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  30. System.out.println(response.body().string());
  31. }

Post方式提交文件

           
  1. public static final MediaType MEDIA_TYPE_MARKDOWN
  2. = MediaType.parse("text/x-markdown; charset=utf-8");
  3. private final OkHttpClient client = new OkHttpClient();
  4. public void run() throws Exception {
  5. File file = new File("README.md");
  6. Request request = new Request.Builder()
  7. .url("https://api.github.com/markdown/raw")
  8. .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
  9. .build();
  10. Response response = client.newCall(request).execute();
  11. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  12. System.out.println(response.body().string());
  13. }

Post方式提交表单

使用 FormEncodingBuilder来构建和HTML <form>标签相同效果的请求体。键值对将使用一种HTML兼容形式的URL编码来进行编码。
          
  1. private final OkHttpClient client = new OkHttpClient();
  2. public void run() throws Exception {
  3. RequestBody formBody = new FormEncodingBuilder()
  4. .add("search", "Jurassic Park")
  5. .build();
  6. Request request = new Request.Builder()
  7. .url("https://en.wikipedia.org/w/index.php")
  8. .post(formBody)
  9. .build();
  10. Response response = client.newCall(request).execute();
  11. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  12. System.out.println(response.body().string());
  13. }

Post方式提交分块请求

MultipartBuilder可以构建复杂的请求体,与HTML文件上传形式兼容。多块请求体中每块请求都是一个请求体,可以定义自己的请求头。这些请求头可以用来描述这块请求,例如他的 Content-Disposition。如果 Content-LengthContent-Type可用的话,他们会被自动添加到请求头中。
           
  1. private static final String IMGUR_CLIENT_ID = "...";
  2. private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
  3. private final OkHttpClient client = new OkHttpClient();
  4. public void run() throws Exception {
  5. // Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
  6. RequestBody requestBody = new MultipartBuilder()
  7. .type(MultipartBuilder.FORM)
  8. .addPart(
  9. Headers.of("Content-Disposition", "form-data; name=\"title\""),
  10. RequestBody.create(null, "Square Logo"))
  11. .addPart(
  12. Headers.of("Content-Disposition", "form-data; name=\"image\""),
  13. RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
  14. .build();
  15. Request request = new Request.Builder()
  16. .header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
  17. .url("https://api.imgur.com/3/image")
  18. .post(requestBody)
  19. .build();
  20. Response response = client.newCall(request).execute();
  21. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  22. System.out.println(response.body().string());
  23. }

使用Gson来解析JSON响应

Gson是一个在JSON和Java对象之间转换非常方便的api。这里我们用Gson来解析Github API的JSON响应。
注意: ResponseBody.charStream()使用响应头 Content-Type指定的字符集来解析响应体。默认是UTF-8。
            
  1. rivate final OkHttpClient client = new OkHttpClient();
  2. private final Gson gson = new Gson();
  3. public void run() throws Exception {
  4. Request request = new Request.Builder()
  5. .url("https://api.github.com/gists/c2a7c39532239ff261be")
  6. .build();
  7. Response response = client.newCall(request).execute();
  8. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  9. Gist gist = gson.fromJson(response.body().charStream(), Gist.class);
  10. for (Map.Entry<String, GistFile> entry : gist.files.entrySet()) {
  11. System.out.println(entry.getKey());
  12. System.out.println(entry.getValue().content);
  13. }
  14. }
  15. static class Gist {
  16. Map<String, GistFile> files;
  17. }
  18. static class GistFile {
  19. String content;
  20. }

响应缓存

为了缓存响应,你需要一个你可以读写的缓存目录,和缓存大小的限制。这个缓存目录应该是私有的,不信任的程序应不能读取缓存内容。
一个缓存目录同时拥有多个缓存访问是错误的。大多数程序只需要调用一次new OkHttp(),在第一次调用时配置好缓存,然后其他地方只需要调用这个实例就可以了。否则两个缓存示例互相干扰,破坏响应缓存,而且有可能会导致程序崩溃。
响应缓存使用HTTP头作为配置。你可以在请求头中添加Cache-Control: max-stale=3600 ,OkHttp缓存会支持。你的服务通过响应头确定响应缓存多长时间,例如使用Cache-Control: max-age=9600

             
  1. private final OkHttpClient client;
  2. public CacheResponse(File cacheDirectory) throws Exception {
  3. int cacheSize = 10 * 1024 * 1024; // 10 MiB
  4. Cache cache = new Cache(cacheDirectory, cacheSize);
  5. client = new OkHttpClient();
  6. client.setCache(cache);
  7. }
  8. public void run() throws Exception {
  9. Request request = new Request.Builder()
  10. .url("http://publicobject.com/helloworld.txt")
  11. .build();
  12. Response response1 = client.newCall(request).execute();
  13. if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);
  14. String response1Body = response1.body().string();
  15. System.out.println("Response 1 response: " + response1);
  16. System.out.println("Response 1 cache response: " + response1.cacheResponse());
  17. System.out.println("Response 1 network response: " + response1.networkResponse());
  18. Response response2 = client.newCall(request).execute();
  19. if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);
  20. String response2Body = response2.body().string();
  21. System.out.println("Response 2 response: " + response2);
  22. System.out.println("Response 2 cache response: " + response2.cacheResponse());
  23. System.out.println("Response 2 network response: " + response2.networkResponse());
  24. System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
  25. }

扩展

在这一节还提到了下面一句:
There are cache headers to force a cached response, force a network response, or force the network response to be validated with a conditional GET.

我不是很懂cache,平时用到的也不多,所以把Google在Android Developers一段相关的解析放到这里吧。

Force a Network Response

In some situations, such as after a user clicks a 'refresh' button, it may be necessary to skip the cache, and fetch data directly from the server. To force a full refresh, add the no-cache directive:

             
  1. connection.addRequestProperty("Cache-Control", "no-cache");
If it is only necessary to force a cached response to be validated by the server, use the more efficient max-age=0 instead:
              
  1. connection.addRequestProperty("Cache-Control", "max-age=0");

Force a Cache Response

Sometimes you'll want to show resources if they are available immediately, but not otherwise. This can be used so your application can show something while waiting for the latest data to be downloaded. To restrict a request to locally-cached resources, add the only-if-cached directive:

               
  1. try {
  2. connection.addRequestProperty("Cache-Control", "only-if-cached");
  3. InputStream cached = connection.getInputStream();
  4. // the resource was cached! show it
  5. catch (FileNotFoundException e) {
  6. // the resource was not cached
  7. }
  8. }

This technique works even better in situations where a stale response is better than no response. To permit stale cached responses, use the max-stale directive with the maximum staleness in seconds:
               
  1. int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks staleconnection.addRequestProperty("Cache-Control", "max-stale=" + maxStale);

取消一个Call

使用Call.cancel()可以立即停止掉一个正在执行的call。如果一个线程正在写请求或者读响应,将会引发IOException。当call没有必要的时候,使用这个api可以节约网络资源。例如当用户离开一个应用时。不管同步还是异步的call都可以取消。
你可以通过tags来同时取消多个请求。当你构建一请求时,使用RequestBuilder.tag(tag)来分配一个标签。之后你就可以用OkHttpClient.cancel(tag)来取消所有带有这个tag的call。

               
  1. private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
  2. private final OkHttpClient client = new OkHttpClient();
  3. public void run() throws Exception {
  4. Request request = new Request.Builder()
  5. .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
  6. .build();
  7. final long startNanos = System.nanoTime();
  8. final Call call = client.newCall(request);
  9. // Schedule a job to cancel the call in 1 second.
  10. executor.schedule(new Runnable() {
  11. @Override public void run() {
  12. System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
  13. call.cancel();
  14. System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
  15. }
  16. }, 1, TimeUnit.SECONDS);
  17. try {
  18. System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
  19. Response response = call.execute();
  20. System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
  21. (System.nanoTime() - startNanos) / 1e9f, response);
  22. } catch (IOException e) {
  23. System.out.printf("%.2f Call failed as expected: %s%n",
  24. (System.nanoTime() - startNanos) / 1e9f, e);
  25. }
  26. }

超时

没有响应时使用超时结束call。没有响应的原因可能是客户点链接问题、服务器可用性问题或者这之间的其他东西。OkHttp支持连接,读取和写入超时。

               
  1. private final OkHttpClient client;
  2. public ConfigureTimeouts() throws Exception {
  3. client = new OkHttpClient();
  4. client.setConnectTimeout(10, TimeUnit.SECONDS);
  5. client.setWriteTimeout(10, TimeUnit.SECONDS);
  6. client.setReadTimeout(30, TimeUnit.SECONDS);
  7. }
  8. public void run() throws Exception {
  9. Request request = new Request.Builder()
  10. .url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
  11. .build();
  12. Response response = client.newCall(request).execute();
  13. System.out.println("Response completed: " + response);
  14. }

每个call的配置

使用OkHttpClient,所有的HTTP Client配置包括代理设置、超时设置、缓存设置。当你需要为单个call改变配置的时候,clone 一个 OkHttpClient。这个api将会返回一个浅拷贝(shallow copy),你可以用来单独自定义。下面的例子中,我们让一个请求是500ms的超时、另一个是3000ms的超时。

               
  1. private final OkHttpClient client = new OkHttpClient();
  2. public void run() throws Exception {
  3. Request request = new Request.Builder()
  4. .url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.
  5. .build();
  6. try {
  7. Response response = client.clone() // Clone to make a customized OkHttp for this request.
  8. .setReadTimeout(500, TimeUnit.MILLISECONDS)
  9. .newCall(request)
  10. .execute();
  11. System.out.println("Response 1 succeeded: " + response);
  12. } catch (IOException e) {
  13. System.out.println("Response 1 failed: " + e);
  14. }
  15. try {
  16. Response response = client.clone() // Clone to make a customized OkHttp for this request.
  17. .setReadTimeout(3000, TimeUnit.MILLISECONDS)
  18. .newCall(request)
  19. .execute();
  20. System.out.println("Response 2 succeeded: " + response);
  21. } catch (IOException e) {
  22. System.out.println("Response 2 failed: " + e);
  23. }
  24. }

处理身份验证

相关资料:HTTP AUTH 那些事 - 王绍全的博客 - 博客频道 - youkuaiyun.com 


有些网络请求是需要用户名密码登录的,如果没提供登录需要的信息,那么会得到401 Not Authorized未授权的错误,这时候Okhttp会自动查找是否配置了Authenticator,如果配置过Authenticator,会用Authenticator中包含的登录相关的信息构建一个新的Request,尝试再次发送HTTP请求。

看下面这篇博客:

http://blog.youkuaiyun.com/iispring/article/details/51661195


                
  1. private final OkHttpClient client;
  2. public Authenticate() {
  3. client = new OkHttpClient.Builder()
  4. .authenticator(new Authenticator() {
  5. @Override public Request authenticate(Route route, Response response) throws IOException {
  6. System.out.println("Authenticating for response: " + response);
  7. System.out.println("Challenges: " + response.challenges());
  8. String credential = Credentials.basic("jesse", "password1");
  9. return response.request().newBuilder()
  10. .header("Authorization", credential)
  11. .build();
  12. }
  13. })
  14. .build();
  15. }
  16. public void run() throws Exception {
  17. Request request = new Request.Builder()
  18. .url("http://publicobject.com/secrets/hellosecret.txt")
  19. .build();
  20. Response response = client.newCall(request).execute();
  21. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  22. System.out.println(response.body().string());
  23. }


另外一篇文章讲述了cookie&Headers(响应头)的关系。

资源地址:http://blog.youkuaiyun.com/iispring/article/details/51661195


以下示例演示了如何同步发送GET请求,输出响应头以及将响应体转换为字符串。


              
  1. private final OkHttpClient client = new OkHttpClient();
  2. public void run() throws Exception {
  3. Request request = new Request.Builder()
  4. .url("http://publicobject.com/helloworld.txt")
  5. .build();
  6. Response response = client.newCall(request).execute();
  7. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  8. Headers responseHeaders = response.headers();
  9. for (int i = 0; i < responseHeaders.size(); i++) {
  10. System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
  11. }
  12. System.out.println(response.body().string());
  13. }

下面对以上代码进行简单说明:

  • client执行newCall方法会得到一个Call对象,表示一个新的网络请求。

  • Call对象的execute方法是同步方法,会阻塞当前线程,其返回Response对象。

  • 通过Response对象的isSuccessful()方法可以判断请求是否成功。

  • 通过Response的headers()方法可以得到响应头Headers对象,可以通过for循环索引遍历所有的响应头的名称和值。可以通过Headers.name(index)方法获取响应头的名称,通过Headers.value(index)方法获取响应头的值。

  • 除了索引遍历,通过Headers.get(headerName)方法也可以获取某个响应头的值,比如通过headers.get(“Content-Type”)获得服务器返回给客户端的数据类型。但是服务器返回给客户端的响应头中有可能有多个重复名称的响应头,比如在某个请求中,服务器要向客户端设置多个Cookie,那么会写入多个Set-Cookie响应头,且这些Set-Cookie响应头的值是不同的,访问百度首页,可以看到有7个Set-Cookie的响应头,如下图所示:

  • 这里写图片描述

为了解决同时获取多个name相同的响应头的值,Headers中提供了一个public List<String> values(String name)方法,该方法会返回一个List<String>对象,所以此处通过Headers对象的values(‘Set-Cookie’)可以获取全部的Cookie信息,如果调用Headers对象的get(‘Set-Cookie’)方法,那么只会获取最后一条Cookie信息。

通过Response对象的body()方法可以得到响应体ResponseBody对象,调用其string()方法可以很方便地将响应体中的数据转换为字符串,该方法会将所有的数据放入到内存之中,所以如果数据超过1M,最好不要调用string()方法以避免占用过多内存,这种情况下可以考虑将数据当做Stream流处理。


工作线程 :非UI线程。



添加请求头

同样的,也可能同时存在多个名称一样的请求头。响应头的读取我们在上文已经说过了,在此不再赘述。一般情况下,我们只需要调用 header(name, value)方法就可以设置请求头的name和value,调用该方法会确保整个请求头中不会存在多个名称一样的name。如果想添加多个name相同的请求头,应该调用 addHeader(name, value)方法,这样可以添加重复name的请求头,其value可以不同,例如如下所示:

            
  1. private final OkHttpClient client = new OkHttpClient();
  2. public void run() throws Exception {
  3. Request request = new Request.Builder()
  4. .url("https://api.github.com/repos/square/okhttp/issues")
  5. .header("User-Agent", "OkHttp Headers.java")
  6. .addHeader("Accept", "application/json; q=0.5")
  7. .addHeader("Accept", "application/vnd.github.v3+json")
  8. .build();
  9. Response response = client.newCall(request).execute();
  10. if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  11. System.out.println("Server: " + response.header("Server"));
  12. System.out.println("Date: " + response.header("Date"));
  13. System.out.println("Vary: " + response.headers("Vary"));
  14. }


一次HTTP请求实际上可以分为三步:

  1. 客户端与服务器建立连接
  2. 客户端发送请求数据到服务器,即数据上传
  3. 服务器将响应数据发送给客户端,即数据下载

由于网络、服务器等各种原因,这三步中的每一步都有可能耗费很长时间,导致整个HTTP请求花费很长时间或不能完成。

为此,可以通过OkHttpClient.BuilderconnectTimeout()方法设置客户端和服务器建立连接的超时时间,通过writeTimeout()方法设置客户端上传数据到服务器的超时时间,通过readTimeout()方法设置客户端从服务器下载响应数据的超时时间。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值