You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中使用Retrofit同步方式实现图片上传?

使用Retrofit同步方式实现Android图片上传

嘿,我来帮你把之前Volley的异步图片上传改成Retrofit的同步实现,其实逻辑和异步类似,只是请求执行方式不同,咱们一步步来:

1. 先添加Retrofit相关依赖

首先在你的app模块的build.gradle(Module级别)里添加必要的依赖,Retrofit底层依赖OkHttp,还要加处理Multipart请求的转换器:

dependencies {
    // Retrofit核心库
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    // 用于处理字符串响应的转换器
    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
    // OkHttp(可指定版本,增强网络请求配置)
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
}

2. 定义Retrofit上传接口

因为是同步请求,接口方法不需要Callback参数,直接返回Response<ResponseBody>,这样调用时会阻塞当前线程直到请求完成:

import okhttp3.MultipartBody;
import okhttp3.ResponseBody;
import retrofit2.Response;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;

public interface ImageUploadService {
    // Multipart注解标记这是多部分表单请求
    @Multipart
    @POST("你的上传接口路径") // 替换成原UPLOAD_URL里的接口路径部分,比如"/upload/image"
    Response<ResponseBody> uploadImage(@Part MultipartBody.Part image);
}

3. 编写同步上传逻辑(Java版)

注意:同步请求绝对不能在主线程执行,否则会触发NetworkOnMainThreadException,所以我们把上传逻辑放在子线程里,用Thread实现:

private void uploadImageSync(final String imagePath) {
    // 启动子线程执行同步请求
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                // 1. 配置OkHttpClient,设置超时时间
                OkHttpClient okHttpClient = new OkHttpClient.Builder()
                        .connectTimeout(30, TimeUnit.SECONDS)
                        .readTimeout(30, TimeUnit.SECONDS)
                        .build();

                // 2. 创建Retrofit实例,传入基础URL
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("你的基础URL") // 替换成原UPLOAD_URL的基础部分,比如"https://your-domain.com/api/"
                        .client(okHttpClient)
                        .addConverterFactory(ScalarsConverterFactory.create())
                        .build();

                // 3. 创建接口实例
                ImageUploadService uploadService = retrofit.create(ImageUploadService.class);

                // 4. 将本地图片文件转成Multipart表单的Part
                File imageFile = new File(imagePath);
                RequestBody requestFile = RequestBody.create(MediaType.parse("image/*"), imageFile);
                // 第一个参数"image"是接口要求的表单字段名,要和后端保持一致
                MultipartBody.Part imagePart = MultipartBody.Part.createFormData("image", imageFile.getName(), requestFile);

                // 5. 执行同步请求(这里会阻塞当前线程,直到请求完成)
                Response<ResponseBody> response = uploadService.uploadImage(imagePart);

                // 6. 切换回主线程处理结果、更新UI
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // 关闭进度对话框
                        loading.dismiss();
                        if (response.isSuccessful()) {
                            try {
                                String responseContent = response.body().string();
                                Toast.makeText(ImageUploadActivity.this, "上传成功:" + responseContent, Toast.LENGTH_SHORT).show();
                            } catch (IOException e) {
                                e.printStackTrace();
                                Toast.makeText(ImageUploadActivity.this, "解析响应失败", Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            try {
                                String errorMsg = response.errorBody().string();
                                Toast.makeText(ImageUploadActivity.this, "上传失败:" + errorMsg, Toast.LENGTH_SHORT).show();
                            } catch (IOException e) {
                                e.printStackTrace();
                                Toast.makeText(ImageUploadActivity.this, "上传失败", Toast.LENGTH_SHORT).show();
                            }
                        }
                    }
                });

            } catch (Exception e) {
                e.printStackTrace();
                // 出错时回到主线程提示
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        loading.dismiss();
                        Toast.makeText(ImageUploadActivity.this, "上传出错:" + e.getMessage(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    }).start();
}

4. 调用同步上传方法

在你原来调用Volley的uploadImage方法的地方,换成调用这个同步方法即可,记得先显示进度对话框:

// 显示上传进度对话框
loading = ProgressDialog.show(this, "上传中", "请稍候...", false, false);
// 调用同步上传方法
uploadImageSync(image_path);

几个关键提醒

  • 必须在子线程执行同步请求:Android严格禁止主线程执行网络操作,一定要把同步请求放在子线程里。
  • 异常处理不能少:网络请求可能遇到超时、无网络、服务器错误等情况,一定要用try-catch包裹,避免程序崩溃。
  • UI操作要回主线程:关闭对话框、显示Toast这些UI操作必须在主线程执行,所以请求完成后要通过runOnUiThread切换线程。

内容的提问来源于stack exchange,提问作者Mobile Test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:46:07