安卓 OkHttp进阶使用(异步请求,传输Json、File对象)(28)

本文介绍如何使用OkHttp库实现多种异步网络请求,包括GET、POST请求,并演示了如何传输JSON及文件对象。通过具体代码示例,读者可以学习到如何处理请求的成功与失败响应,并更新UI。

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

使用OkHttp实现更多功能(Get、Post异步请求、使用Post传输Json、File对象)

参考文章:https://blog.youkuaiyun.com/fightingXia/article/details/70947701

public class OkHttpGetAsyncActivity extends Activity {

    private final int OKHTTP_GET_SUCCESS = 0;
    private final int OKHTTP_GET_FAIL = 1;

    private Button send_http;
    private TextView get_http;
    String responseData;

    //接收OkHttp中发送的Message,根据不同的Message进行不同的UI操作
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case OKHTTP_GET_SUCCESS:
                    Toast.makeText(OkHttpGetAsyncActivity.this, "Success", Toast.LENGTH_SHORT).show();
                    get_http.setText(responseData);
                    break;
                case OKHTTP_GET_FAIL:
                    Toast.makeText(OkHttpGetAsyncActivity.this, "Failure", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ok_http);

        send_http = findViewById(R.id.send_Okhttp);
        get_http = findViewById(R.id.get_Okhttp);

        send_http.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //这里实现Get请求
//                getDataAsync();
                //这里实现Post请求(传递键值对参数)
//                getDataPostAsync();
                //这里实现Post请求(传递Json对象)
//                getDataPostJsonAsync();
                //这里实现Post请求(传递File对象)
                getDataPostFileAsync();
            }
        });
        get_http.setMovementMethod(new ScrollingMovementMethod());
    }

    private void getDataAsync() {
        //Get的异步请求不需要开启子线程,但是在其回调函数中还是在子线程中执行
        //所以更改UI还是需要在主线程中
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = new Message();
                message.what = OKHTTP_GET_FAIL;
                handler.sendMessage(message);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if(response.isSuccessful()){
                    responseData = response.body().string();

                    Message message = new Message();
                    message.what = OKHTTP_GET_SUCCESS;
                    handler.sendMessage(message);
                }
            }
        });
    }

    private void getDataPostAsync() {
        //Post的异步请求不需要开启子线程,但是在其回调函数中还是在子线程中执行
        //所以更改UI还是需要在主线程中
        OkHttpClient client = new OkHttpClient();
        RequestBody requestBody = new FormBody.Builder()
                .add("arg1","123")
                .add("arg2","123456")
                .build();
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .post(requestBody)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = new Message();
                message.what = OKHTTP_GET_FAIL;
                Log.v("onFailure",message.what + "");
                handler.sendMessage(message);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.v("onResponse","onResponse ");
                //response.isSuccessful()这个布尔值代表的是,你使用Post请求过后,返回时是否成功
                //比如我们发送一个错误参数的Post请求,如果添加了response.isSuccessful(),那么他的条件语句不会触发,即response.isSuccessful() == false。
//                if(response.isSuccessful()){
                    responseData = response.body().string();

                    Message message = new Message();
                    message.what = OKHTTP_GET_SUCCESS;
                    handler.sendMessage(message);
//                }
            }
        });
    }

    private void getDataPostJsonAsync() {
        OkHttpClient client =  new OkHttpClient();
        //设置数据类型为JSON类型
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        //JSON格式数据
        String jsonStr = "{\"arg1\":\"123456\",\"arg2\":\"525\"}";
        RequestBody requestBody = RequestBody.create(JSON, jsonStr);
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .post(requestBody)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = new Message();
                message.what = OKHTTP_GET_FAIL;
                Log.v("onFailure",message.what + "");
                handler.sendMessage(message);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.v("onResponse","onResponse ");
                //response.isSuccessful()这个布尔值代表的是,你使用Post请求过后,返回时是否成功
                //比如我们发送一个错误参数的Post请求,如果添加了response.isSuccessful(),那么他的条件语句不会触发,即response.isSuccessful() == false。
//                if(response.isSuccessful()){
                responseData = response.body().string();

                Message message = new Message();
                message.what = OKHTTP_GET_SUCCESS;
                handler.sendMessage(message);
//                }
            }
        });
    }


    private void getDataPostFileAsync() {
        OkHttpClient client = new OkHttpClient();
        //设置一种File对象
        MediaType fileType = MediaType.parse("File/*");
        File file = new File("FilePath");
        RequestBody requestBody = RequestBody.create(fileType, file);
        Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .post(requestBody)
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Message message = new Message();
                message.what = OKHTTP_GET_FAIL;
                Log.v("onFailure",message.what + "");
                handler.sendMessage(message);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.v("onResponse","onResponse ");
                //response.isSuccessful()这个布尔值代表的是,你使用Post请求过后,返回时是否成功
                //比如我们发送一个错误参数的Post请求,如果添加了response.isSuccessful(),那么他的条件语句不会触发,即response.isSuccessful() == false。
//                if(response.isSuccessful()){
                responseData = response.body().string();

                Message message = new Message();
                message.what = OKHTTP_GET_SUCCESS;
                handler.sendMessage(message);
//                }
            }
        });
    }
}

<think>我们有两个引用,其中引用[1]和引用[2]都提供了发送application/json请求的示例代码。用户要求一个具体的示例代码,因此我们可以结合这两个引用来提供一个更完整的示例。 注意点: 1. 使用OkHttp发送POST请求请求体为JSON字符串。 2. 设置请求头Content-Type为application/json。 3. 使用RequestBody.create()方法创建请求体。 4. 使用OkHttpClient的newCall()方法发送请求并获取响应。 我们将提供一个同步请求的示例,并包括异常处理和资源释放。 示例代码: ```java import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import java.io.IOException; public class OkHttpJsonExample { // 定义JSON媒体类型 private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static void main(String[] args) { String url = "https://api.example.com/endpoint"; // 替换为实际URL String json = "{\"key1\":\"value1\", \"key2\":\"value2\"}"; // JSON字符串 try { String response = postJson(url, json); System.out.println(response); } catch (IOException e) { e.printStackTrace(); } } public static String postJson(String url, String json) throws IOException { OkHttpClient client = new OkHttpClient(); // 创建请求体 RequestBody body = RequestBody.create(json, JSON); // 注意:在OkHttp 3.12.x及之前版本,使用create方法 // 在OkHttp 4.x及以上版本,RequestBody.create方法有所变化,推荐使用: // RequestBody body = RequestBody.create(json, JSON); // 构建请求 Request request = new Request.Builder() .url(url) .post(body) .build(); // 发送请求并处理响应 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } return response.body().string(); } } } ``` 注意:上述代码中,我们使用了try-with-resources来确保Response资源被正确关闭。另外,我们检查了响应是否成功(状态码在200-299之间)。 但是,请注意OkHttp的版本差异: - 在OkHttp 3.12.x及之前版本,`RequestBody.create`方法有两个参数:第一个是字符串,第二个是MediaType。 - 在OkHttp 4.x及以上版本,`RequestBody.create`方法被标记为过时,推荐使用`RequestBody.create(String, MediaType)`的静态方法,但注意参数顺序:先入字符串,再入MediaType。或者,也可以使用`RequestBody.create`的重载方法(如入字节数组)。但是,对于字符串,我们仍然可以使用`RequestBody.create(json, JSON)`。 如果使用的是OkHttp 4.x,并且遇到方法过时的情况,可以改用: ```java RequestBody body = RequestBody.create(json, JSON); ``` 因为即使标记为过时,这个方法在4.x中仍然可用。 另外,如果希望添加请求头,可以在构建请求时添加,例如: ```java Request request = new Request.Builder() .url(url) .addHeader("Content-Type", "application/json") .addHeader("Authorization", "Bearer token") .post(body) .build(); ``` 但是,通常我们已经在RequestBody中指定了MediaType,所以Content-Type头会自动设置为"application/json; charset=utf-8"。如果额外设置Content-Type头,可能会覆盖掉默认值,但这里设置的值和默认值一致,所以也可以不设置。 根据引用[1],我们还可以在构建请求时添加多个请求头。如果需要,可以按照引用[1]中的方式构建Headers。 现在,我们提供一个更通用的方法,可以添加自定义请求头(参考引用[1]): ```java import okhttp3.Headers; import java.util.Map; public static String postJsonWithHeaders(String url, Map<String, String> headers, String json) throws IOException { OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(json, JSON); // 构建请求头 Headers.Builder headersBuilder = new Headers.Builder(); if (headers != null) { for (Map.Entry<String, String> entry : headers.entrySet()) { headersBuilder.add(entry.getKey(), entry.getValue()); } } Request request = new Request.Builder() .url(url) .headers(headersBuilder.build()) .post(body) .build(); try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("Unexpected code " + response); } return response.body().string(); } } ``` 这样,用户就可以入自定义的请求头了。 最后,我们需要注意:`response.body().string()`只能调用一次,因为它会消耗整个响应流,再次调用会抛出异常。 因此,我们返回字符串后,调用者可以按需使用。 如果用户需要异步请求,可以参考之前的回答中的异步示例。 现在,我们根据用户的问题,提供发送application/json请求的代码示例,并生成相关问题。</think>### OKHTTP 发送 application/json 请求的完整示例 以下是使用 OkHttp 发送 JSON 格式 POST 请求的完整代码示例(基于引用[1][2]的最佳实践): ```java import okhttp3.*; import java.io.IOException; import java.util.Map; public class OkHttpJsonExample { // 发送 JSON POST 请求的通用方法 public static String postJson(String url, Map<String, String> headers, String jsonBody) throws IOException { // 1. 创建 OkHttpClient 实例 OkHttpClient client = new OkHttpClient(); // 2. 创建 JSON 媒体类型 MediaType JSON = MediaType.parse("application/json; charset=utf-8"); // 3. 构建请求体 RequestBody body = RequestBody.create(jsonBody, JSON); // 引用[2] // 4. 构建请求头 Headers.Builder headersBuilder = new Headers.Builder(); for (Map.Entry<String, String> entry : headers.entrySet()) { headersBuilder.add(entry.getKey(), entry.getValue()); } // 5. 创建请求对象 Request request = new Request.Builder() .url(url) .headers(headersBuilder.build()) .post(body) // 设置 POST 请求 .build(); // 引用[1] // 6. 发送请求并处理响应 try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) { throw new IOException("请求失败: " + response.code()); } return response.body().string(); } } // 使用示例 public static void main(String[] args) { String url = "https://api.example.com/data"; String jsonPayload = "{\"username\":\"test\", \"password\":\"123456\"}"; // 设置请求头 Map<String, String> headers = Map.of( "Content-Type", "application/json", "Authorization", "Bearer your_token_here" ); try { String response = postJson(url, headers, jsonPayload); System.out.println("响应内容: " + response); } catch (IOException e) { e.printStackTrace(); } } } ``` ### 关键点说明 1. **媒体类型设置** `MediaType.parse("application/json; charset=utf-8")` 确保正确设置 JSON 格式和编码 2. **请求头管理** 使用 `Headers.Builder` 动态添加请求头(如认证令牌等) 3. **资源自动释放** `try-with-resources` 语法确保响应资源自动关闭 4. **错误处理** `response.isSuccessful()` 检查 HTTP 状态码(200-299) 5. **JSON 格式要求** 请求体必须是有效的 JSON 字符串,如: ```java // 使用 JSON 库生成更安全 String json = "{\"key1\":\"value1\", \"key2\":42}"; ``` ### 常见问题解决 1. **字符编码问题** 确保 JSON 字符串使用 UTF-8 编码: ```java String json = new String("{\"name\":\"中文\"}".getBytes(), StandardCharsets.UTF_8); ``` 2. **大 JSON 处理** 使用流式处理避免内存溢出: ```java RequestBody body = RequestBody.create( Files.asByteSource(new File("large.json")), JSON ); ``` 3. **异步请求示例** ```java client.newCall(request).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { // 在后台线程处理响应 } @Override public void onFailure(Call call, IOException e) { // 错误处理 } }); ``` > 注意:`response.body().string()` 只能调用一次,多次调用会抛出异常[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值