OkHttp的基本使用

一、简介

OkHttp是由square公司开发,Android中公认最好用的网络请求框架,在接口封装上做的简单易用

它由以下默认特性

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
  • 使用连接池减少请求延时
  • 透明的GZIP压缩减少响应数据的大小
  • 缓存响应内容,避免一些完全重复的请求

出现一般的网络问题时OkHttp 会自动恢复:如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会尝试你配置的其他IP。

二、引入

官网最新版本目前是4.10.x,使用的是Kotlin编写的。这里我使用的是3.14.x版本,使用的Java

引入依赖

    implementation 'com.squareup.okhttp3:okhttp:3.14.7'
    implementation 'com.squareup.okio:okio:1.17.5'

OkHttp 底层依赖 Okio。它利用 Okio 的 Source 和 Sink 高效读写字节流,其缓冲管理机制能让网络数据处理更稳定,还借助 Okio 高效处理数据,如编码解码、压缩解压缩。

配置权限
除了网络权限外,如果还使用网络请求的缓存功能,那么还要申请读写外存的权限(Android10以后,可能还需要一些额外的适配)

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

三、使用方式

基本步骤如下

  1. 通过构造者模式构建OkHttpClientRequest对象
  2. 调用okHttpClient.newCall(request)生成Call对象
  3. Call.enqueue()/Call.execute() 发起请求(异步/同步)

3.1 get请求

  OkHttpClient httpClient = new OkHttpClient();

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

       new Thread(()->{
           try {
               // 同步请求,要放到子线程
               Response response =httpClient.newCall(request).execute();
               Log.i(TAG, "okhttp  execute response:"+ response.body().string());
           } catch (IOException e) {
               throw new RuntimeException(e);
           }
       }).start();

execute方法执行的是同步请求,必须放到子线程,如果想在主线程执行,可以使用异步请求

3.1.1 异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
            	// response.body() 必须关闭,且只能使用一次,
            	// 多次使用报 java.lang.IllegalStateException: closed
                Log.i(TAG, "okhttp enqueue: onResponse:"+ response.body().string());
                response.body().close()
            }
        });

call.enqueue会异步执行,需要注意的是,两个回调方法onFailureonResponse是执行在子线程的,所以如果想要执行UI操作,需要使用Handler切换到UI线程

请求回调的两个方法是指 传输层的失败和成功onFailure通常是connection连接失败或读写超时;onResponse是指成功的从服务器获取到了结果,但是这个结果的响应码可能是404、500等,也可能就是200(response.code()的取值)。

3.1.2 取消请求

每一个Call只能执行一次。 如果想要取消正在执行的请求,可以使用call.cancel(),通常在离开页面时要取消执行的请求,来防止内存泄漏。

3.2 POST 请求

对于POST请求,需要对设置请求体和请求头

 OkHttpClient httpClient = new OkHttpClient();

    MediaType contentType = MediaType.parse("application/json; charset=utf-8");
    String content = "hello!";
    // 默认媒体类型 application/x-www-form-urlencoded
    RequestBody body = RequestBody.create(contentType, content);

	Request request = new Request.Builder()
	      .url("http://your-api-url-here")
	      .post(body)
	      .build();
	try (Response response = client.newCall(request).execute()) {
	    if (response.isSuccessful()) {
	        String responseBody = response.body().string();
	        System.out.println("Response: " + responseBody);
	    } else {
	        System.out.println("Error: " + response.code());
	    }
	} catch (Exception e) {
	    e.printStackTrace();
	}
3.2.1 post请求提交String、文件

传入RequestBodyMediaType 还可以是其他类型,如客户端要给后台发送json字符串、发送一张图片,那么可以定义为:

// RequestBody:jsonBody,json字符串
String json = "jsonString";
RequestBody jsonBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);

//RequestBody:fileBody, 上传文件
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOAD);
File file = new File(path, "1.png");
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);

3.2.2 post请求提交表单

OK HTTP还提供了FormBody用于提交表单键值对

//RequestBody:FormBody,表单键值对
RequestBody formBody = new FormBody.Builder()
        .add("username", "lyz")
        .add("password", "xml")
        .build();
3.2.3 post请求提交复杂请求体

在实际业务中,一个post请求往往需要包含string、文件、表单等多种类型的数据,如注册:用户填写完姓名、电话,同时要上传头像图片,这时就要用到MultipartBody了。

        OkHttpClient httpClient = new OkHttpClient();


        //RequestBody:fileBody,上传文件
        File file = drawableToFile(this, R.mipmap.bigpic, new File("00.jpg"));
        RequestBody fileBody = RequestBody.create(MediaType.parse("image/jpg"), file);


        //RequestBody:multipartBody, 多类型 (用户名、密码、头像)
        MultipartBody multipartBody = new MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addFormDataPart("username", "lyz")
                .addFormDataPart("phone", "123456")
                .addFormDataPart("touxiang", "tx.png", fileBody)
                .build();


        Request req = new Request.Builder()
                .url("/your-api-url-here")
                .post(multipartBody)
                .build();

        Call call = httpClient.newCall(req);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

                Log.i(TAG, "okHttpPost enqueue: \n onFailure:"+ call.request().toString() +"\n body:" +call.request().body().contentType()
                +"\n IOException:"+e.getMessage());
            }

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

3.3 请求配置项

配置分为全局配置和单请求配置

  • 在构建的OkHttpClient实例上设置的配置,会应用在该实例发送的所有请求上
    通常OkHttpClient实例是全局唯一的,这样这些基本配置就是统一,
   OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS) 
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS) // 
                .cache(new Cache(getExternalCacheDir(), 500 * 1024 * 1024)) // 缓存位置,最大缓存大小
                .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        String url = request.url().toString();
                        Log.i(TAG, "intercept: proceed start: url"+ url+ ", at "+System.currentTimeMillis());
                        Response response = chain.proceed(request);
                        ResponseBody body = response.body();
                        Log.i(TAG, "intercept: proceed end: url"+ url+ ", at "+System.currentTimeMillis());
                        return response;
                    }
                })
                .build();
  • 单个请求配置
   Request getRequest = new Request.Builder()
                .url("http://yun918.cn/study/public/file_upload.php")
                .post(multipartBody)
                .addHeader("key","value") // 添加请求头
                .cacheControl(CacheControl.FORCE_NETWORK) // 设置此次请求是能使用网络,不用缓存。
                .build();

以上,我们已经学会了OkHttp的基本使用了


参考
胡飞洋大神的 网络请求框架OkHttp3全解系列

<think>好的,用户想了解OkHttp3的基本使用方法。我需要先回忆一下OkHttp3的主要功能和常见用途。OkHttp是一个广泛使用的HTTP客户端库,适用于Android和Java应用程序,用于处理网络请求。用户可能是个刚入门的开发者,需要快速上手,所以回答要简明扼要,步骤清晰。 首先,我应该介绍如何引入OkHttp3的依赖,比如在Gradle中添加依赖项。然后,可能需要分几个部分,比如同步请求、异步请求、POST请求、拦截器等常见用法。用户可能关心的是基本使用,不需要太深入的高级功能,但适当提一下拦截器可以展示其扩展性。 需要注意OkHttp3的基本请求流程:创建OkHttpClient实例,构建Request对象,调用newCall方法执行请求,处理响应。同步和异步的区别需要明确说明,同步请求需要在子线程执行,而异步请求通过回调处理结果。 POST请求部分,用户可能需要知道如何提交表单数据和JSON数据,这里要给出具体的示例代码,比如使用FormBody和RequestBody。此外,文件上传作为POST的一个常见场景,也应该包含进去,但要注意代码的正确性,比如正确的MIME类型和MultipartBody的构建。 拦截器部分可以简要说明其用途,比如添加日志或修改请求头,给出一个日志拦截器的例子,这样用户能直观了解如何自定义拦截器。 最后,可能还需要提醒一些注意事项,比如网络权限的添加,在Android中需要在Manifest文件里声明INTERNET权限。此外,提到响应处理时的异常捕获,比如IOException,确保应用的健壮性。 需要检查代码示例是否正确,比如同步请求的execute()方法会阻塞线程,必须放在子线程中执行,而异步请求的enqueue方法会自动在后台线程执行回调。POST请求的MediaType是否正确,特别是JSON的application/json类型是否正确使用。 可能用户在实际使用中会遇到问题,比如依赖无法下载,需要确认是否使用了正确的仓库,或者版本号是否最新。但用户的问题主要是基本使用,所以这些细节可能暂时不需要深入,除非用户后续追问。 总之,结构要清晰,分点说明,代码示例正确且关键部分有注释,注意事项也要提到,帮助用户避免常见错误。确保回答简洁,但覆盖主要的使用场景,让用户能快速上手OkHttp3的基本操作。</think>以下为OkHttp3的基本使用方法和核心步骤: ----- ### 一、添加依赖 ```gradle // Gradle配置 implementation 'com.squareup.okhttp3:okhttp:4.9.3' // 使用最新版本 ``` ----- ### 二、GET请求 #### 同步请求 ```java OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://api.example.com/data") .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { String result = response.body().string(); System.out.println(result); } } catch (IOException e) { e.printStackTrace(); } // 注意:同步请求需在子线程执行 ``` #### 异步请求 ```java client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String result = response.body().string(); System.out.println(result); } } }); ``` ----- ### 三、POST请求 #### 表单提交 ```java RequestBody formBody = new FormBody.Builder() .add("username", "admin") .add("password", "123456") .build(); Request request = new Request.Builder() .url("https://api.example.com/login") .post(formBody) .build(); ``` #### JSON提交 ```java MediaType JSON = MediaType.parse("application/json; charset=utf-8"); String json = "{\"name\":\"Alice\",\"age\":25}"; RequestBody body = RequestBody.create(json, JSON); Request request = new Request.Builder() .url("https://api.example.com/users") .post(body) .build(); ``` ----- ### 四、文件上传 ```java File file = new File("/sdcard/image.jpg"); RequestBody fileBody = RequestBody.create(file, MediaType.parse("image/jpeg")); RequestBody multipartBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", "avatar.jpg", fileBody) .addFormDataPart("description", "用户头像") .build(); Request request = new Request.Builder() .url("https://api.example.com/upload") .post(multipartBody) .build(); ``` ----- ### 五、拦截器使用 ```java // 添加日志拦截器 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)) .build(); // 自定义拦截器(示例:添加公共请求头) .addInterceptor(chain -> { Request original = chain.request(); Request newRequest = original.newBuilder() .header("Authorization", "Bearer token123") .build(); return chain.proceed(newRequest); }) ``` ----- ### 注意事项 1. Android应用需添加网络权限: ```xml <uses-permission android:name="android.permission.INTERNET"/> ``` 2. 响应体处理完成后必须关闭: ```java try (ResponseBody body = response.body()) { String result = body.string(); } ``` 3. 文件上传时注意处理大文件的分块传输 以上为OkHttp3的常用操作,实际开发中可根据需求组合使用这些功能模块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值