android okhttp的基础使用【入门推荐】

发布时间 - 2026-01-10 22:26:05    点击率:

这篇文章主要总结Android著名网络框架-okhttp的基础使用,后续可能会有关于他的高级使用。

okhttp是什么

okhttp是Android端的一个Http客户端,其基础功能相当于Android自带的HttpURLConnection和Apache HTTP Client,但他却比自带的2个Http客户端优越很多,一者是写法简单,二者okhttp处理很多网络复杂问题,如会从很多常用的连接问题中自动恢复。如果您的服务器配置了多个IP地址,当第一个IP连接失败的时候,OkHttp会自动尝试下一个IP。OkHttp还处理了代理服务器问题和SSL握手失败等等很多问题。关于第二者,这篇文章不讨论。

okhttp的导入

Gradle导入

 compile 'com.squareup.okhttp3:okhttp:3.2.0'
 compile 'com.squareup.okio:okio:1.6.0'

okhttp基础使用

这里我们主要介绍简单的使用,介绍内容如下

  1. get请求
  2. post请求,参数是键值对
  3. post请求,多种类型的body
  4. 文件下载
  5. 加入Gson

get请求

get请求分为同步get和异步get,两者的区别主要get的方式是工作在另一个线程还是工作在本线程。请求的方式大同小异。

首先定义一个OkHttpClient对象,如下

private OkHttpClient client = new OkHttpClient();

然后构建一个Request,构建方式如下:

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

这个是最简单的request的构建方式,当然我们可以构建的很复杂。

 Request request = new Request.Builder().
    url("http://www.baidu.com").
    addHeader("User-Agent","android").
    header("Content-Type","text/html; charset=utf-8").
    build();

通过addHeader和header方法为请求增加请求头部,注意使用header(name, value)可以设置唯一的name、value。如果已经有值,旧的将被移除,然后添加新的。使用addHeader(name, value)可以添加多值(添加,不移除已有的)。

同步的get方法,通过client.newCall(request).execute()方法得到请求的response.

 Response response = okHttpClient.newCall(request).execute();

OkHttp封装了很多处理response的方法,比如response.headers()的得到headers.

Headers headers = response.headers();
 for (int i = 0; i < headers.size(); i++) {
System.out.println(headers.name(i) + ": " + headers.value(i)); }

结果如下:

Date: Mon, 18 Apr 2016 05:23:43 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: Keep-Alive
Vary: Accept-Encoding
Set-Cookie: BAIDUID=A323EC9BF678C0EB78E20741FD71211B:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BIDUPSID=A323EC9BF678C0EB78E20741FD71211B; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: PSTM=1460957023; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1434_19672_18281_19690_17948_18205_19558_15952_12257; path=/; domain=.baidu.com
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Cache-Control: private
Cxy_all: baidu+2db7793e0e32b9f6c20be8f623e1ae43
Expires: Mon, 18 Apr 2016 05:22:55 GMT
X-Powered-By: HPHP
Server: BWS/1.1
X-UA-Compatible: IE=Edge,chrome=1
BDPAGETYPE: 1
BDQID: 0xfacc6fc10004ca96
BDUSERID: 0
OkHttp-Sent-Millis: 1460957021226
OkHttp-Received-Millis: 1460957021430

响应报文的实体可以通过response.body().string()获取;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。

异步的get请求得到的response方法是通过如下方法

okHttpClient.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {
      }  
      @Override
      public void onResponse(Call call, Response response) throws IOException {
      }
    });

在onResponse方法中,执行请求成功的代码,onFailure方法中,执行请求失败的代码,下面给一个完整的异步get的栗子

import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.text.method.ScrollingMovementMethod;
import android.widget.TextView;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class MainActivity extends AppCompatActivity {
 private OkHttpClient okHttpClient = new OkHttpClient();
 public TextView show;
 public Handler handler = new Handler();
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  show = (TextView) findViewById(R.id.show);
  show.setMovementMethod(ScrollingMovementMethod.getInstance());
  Request request = new Request.Builder().
    url("http://www.baidu.com").
    addHeader("User-Agent", "android").
    header("Content-Type", "text/html; charset=utf-8").
    get().
    build();
  okHttpClient.newCall(request).enqueue(new Callback() {
   @Override
   public void onFailure(Call call, IOException e) {
   }
   @Override
   public void onResponse(Call call, final Response response) throws IOException {
    final Headers headers = response.headers();
    final String str = response.body().string();
    handler.post(new Runnable() {
     @Override
     public void run() {
      for (int i = 0; i < headers.size(); i++) {
       show.append(headers.name(i) + ": " + headers.value(i));
       show.append(str);
      }
     }
    });
   }
  });
 }
}

其实按照官网说的,回调是发生在response 的headers准备好就发生的,所以有时候请求response的实体部分会发生阻塞。

post请求——键值对为参数。

post请求和get请求除了在构建request上面不同以外,在处理response上面都是一样的,所以下面我们只讨论一下post构建request,当然post也是支持同步post和异步post的,可以参考get方法。

在构建post的request时候,首先用FormBody.Builder去构建request的body部分,栗子如下,当然这是OKHttp3的方法.

FormBody.Builder builder = new FormBody.Builder();
  for(int i = 0 ; i < key.size() ;i ++){
   builder.add(key.get(i),value.get(i));
  }
  RequestBody body = builder.build();

builder中add的是要加入的参数键值对。得到要构造的body后用

Request request = new Request.Builder().url(url).post(body).build();

获得请求的request,后面的操作就和get方法是一样的,这里可以参考异步get的栗子,构建一个post的request.下面的写法原封不变。

post请求--多种类型的body

上文已经说了post和get的用法主要在构建不同的request上面,所以接下来我们主要讨论的也是如何构建request.

参考上面,我们首先要创建一个requestBody,我们可以用下面的方式去构建,当然这也是okhttp3的方法

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

已表单上传的形式去提交post。我们看一下builder的方法

 /** Add a part to the body. */
 public Builder addPart(RequestBody body) {
  return addPart(Part.create(body));
 }
 /** Add a part to the body. */
 public Builder addPart(Headers headers, RequestBody body) {
  return addPart(Part.create(headers, body));
 }
 /** Add a form data part to the body. */
 public Builder addFormDataPart(String name, String value) {
  return addPart(Part.createFormData(name, value));
 }
 /** Add a form data part to the body. */
 public Builder addFormDataPart(String name, String filename, RequestBody body) {
  return addPart(Part.createFormData(name, filename, body));
 }

从这里我们可以看出可以直接用 public Builder addFormDataPart(String name, String filename, RequestBody body)上传一个File,最后一个参数是请求的实体,可以通过 RequestBody.create(final MediaType contentType, final File file) 获得,而MediaType则可以通过下面方法获得

//调用judgeType方法
private static final MediaType MEDIA_TYPE = MediaType.parse(judgeType(fileName);
//judge方法如下
private String judgeType(String path) {
  FileNameMap fileNameMap = URLConnection.getFileNameMap();
  String contentTypeFor = fileNameMap.getContentTypeFor(path);
  if (contentTypeFor == null) {
   contentTypeFor = "application/octet-stream";
  }
  return contentTypeFor;
 }

由于我后台能力比较渣,这里用一个官网的例子来实现一遍我刚才讨论的方法。

MultipartBody.Builder builder = new MultipartBody.Builder()
  .setType(MultipartBody.FORM)
  .addFormDataPart("image", "logo-square.png",
   RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")));
RequestBody requestBody = builder.build();
 Request request = new Request.Builder()
  .header("Authorization", "Client-ID " +"9199fdef135c122")
  .url("https://api.imgur.com/3/image")
  .post(requestBody)
  .build();

当然除了这个方法以外,调用如下方法也是可以的,我们可以利用name和filename自己构造Header传上去。

public Builder addPart(Headers headers, RequestBody body) {
  return addPart(Part.create(headers, body))

栗子如下:

builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + name + "\"; filename=\"" + fileName + "\""),fileBody);

后面的写法和上面类似,这样我们就实现了文件上传的写法。

文件下载

刚才我们上面已经说了,希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。换句话说,文件的下载可以简单的通过get请求,得到相应的response,在把他的实体转换成二进制流写入文件,就是实现了文件的下载。主要的写法就是文件的读写,跟OKHttp关系不大,当然我们也可以用okio来实现文件的读写,这里水平有限就不介绍了。下面给一个简单的例子。

private void _download(final String url, final String destFileDir, final ResultCallback callback) {
  final Request request = new Request.Builder().url(url).build();
  final Call call = okHttpClient.newCall(request);
  call.enqueue(new Callback() {
   @Override
   public void onFailure(Call call, IOException e) {

   }
   @Override
   public void onResponse(Call call, Response response) throws IOException {
    InputStream is = null;
    byte[] buf = new byte[2048];
    int len = 0;
    FileOutputStream fos = null;
    try {
     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();
     //....省略后续对已经保存的文件的操作
    } catch (IOException e) {
     e.printStackTrace();
    }finally {
     try {
      if (is != null) is.close();
     } catch (IOException e) {
     }
     try
     {
      if (fos != null) fos.close();
     } catch (IOException e)
     {
     }
    }
   }
  });
 }

加入Gson

接下来,我们讨论一个很实际的问题,Android的网络请求一般不会去请求一个网站的Html,更多的是请求后台接口的Json文件,所以我们用Gson来处理json的解析。这一部分和前面就不同了,前面多数讲的是如何构建不同的request来得到response,而对响应的结果,处理都是一致的。但这里主要的写法就是用Gson去处理response,而request的构建则根据上面介绍的方法去构建,无需改变。

Gson的导入

compile 'com.google.code.gson:gson:2.6.2'

比如我们后台给出的api是这样一个json文件

{
 "status": 0,
 "intro": "你好",
 "shopName": "byhieg", 
 "message": "查询成功",
}

则我们可以简单的构建这样的一个Test.java文件,如下所示:

public class Test {
 /**
  * status : 0
  * intro : byhieg
  * shopName : byhige
  * message : 查询成功
  */
 private int status;
 private String intro;
 private String shopName;
 private String message;
 public int getStatus() {
  return status;
 }
 public void setStatus(int status) {
  this.status = status;
 }
 public String getIntro() {
  return intro;
 }
 public void setIntro(String intro) {
  this.intro = intro;
 }
 public String getShopName() {
  return shopName;
 }
 public void setShopName(String shopName) {
  this.shopName = shopName;
 }
 public String getMessage() {
  return message;
 }
 public void setMessage(String message) {
  this.message = message;
 }
}

在获得到response之后,用如下代码把Json文件解析成result对象。然后调用result对象的get方法就可以得到json文件中的intro的值和shopname的值,以及status和message.这里就不多介绍了

Test result = new Gson().fromJson(response.body().string,Test.class);

总结

简单介绍了okHttp的使用,对于一些高级用法请关注下篇文章,本人水平有限,如有错误,还望指正。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# android  # okhttp  # 使用  # Android第三方HTTP网络支持包OkHttp的基础使用教程  # Android使用okHttp(get方式)下载图片  # 详解Android中使用OkHttp发送HTTP的post请求的方法  # Android中Retrofit+OkHttp进行HTTP网络编程的使用指南  # Android M(6.x)使用OkHttp包解析和发送JSON请求的教程  # 使用Android的OkHttp包实现基于HTTP协议的文件上传下载  # Android的HTTP扩展包OkHttp中的缓存功能使用方法解析  # Android App开发中HTTP扩展包OkHttp的入门使用指南  # Android中使用OkHttp包处理HTTP的get和post请求的方法  # Android中的Retrofit+OkHttp+RxJava缓存架构使用  # 的是  # 键值  # 说了  # 可以用  # 你想  # 我们可以  # 可以通过  # 这篇文章  # 自带  # 来实现  # 官网  # 移除  # 都是  # 客户端  # 这是  # 您的  # 实现了  # 构建一个  # 上传  # 这一 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  网站图片在线制作软件,怎么在图片上做链接?  香港服务器部署网站为何提示未备案?  网站制作软件免费下载安装,有哪些免费下载的软件网站?  如何在香港服务器上快速搭建免备案网站?  Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程  如何在云主机上快速搭建多站点网站?  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  如何快速搭建高效WAP手机网站吸引移动用户?  Android使用GridView实现日历的简单功能  Laravel怎么在Controller之外的地方验证数据  如何确认建站备案号应放置的具体位置?  Laravel控制器是什么_Laravel MVC架构中Controller的作用与实践  如何挑选最适合建站的高性能VPS主机?  零服务器AI建站解决方案:快速部署与云端平台低成本实践  三星、SK海力士获美批准:可向中国出口芯片制造设备  七夕网站制作视频,七夕大促活动怎么报名?  Laravel如何升级到最新版本?(升级指南和步骤)  Android 常见的图片加载框架详细介绍  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  详解Android——蓝牙技术 带你实现终端间数据传输  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  香港服务器建站指南:免备案优势与SEO优化技巧全解析  JavaScript如何实现路由_前端路由原理是什么  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  如何在景安服务器上快速搭建个人网站?  北京企业网站设计制作公司,北京铁路集团官方网站?  青岛网站建设如何选择本地服务器?  如何基于PHP生成高效IDC网络公司建站源码?  在线制作视频网站免费,都有哪些好的动漫网站?  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  百度浏览器网页无法复制文字怎么办 百度浏览器复制修复  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  香港服务器如何优化才能显著提升网站加载速度?  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  Android滚轮选择时间控件使用详解  西安专业网站制作公司有哪些,陕西省建行官方网站?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  js实现获取鼠标当前的位置  实例解析angularjs的filter过滤器  音乐网站服务器如何优化API响应速度?  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  Laravel如何实现一对一模型关联?(Eloquent示例)  Windows10如何更改计算机工作组_Win10系统属性修改Workgroup  原生JS获取元素集合的子元素宽度实例