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

Retrofit2多部分文件上传单类正常多类使用崩溃问题排查

Retrofit2 多场景多文件上传崩溃问题解决指南

我之前也碰到过类似的Retrofit多文件上传在跨场景下崩溃的问题,结合你给出的ART崩溃日志来看,大概率是Retrofit实例复用不当、请求参数构建不一致引发的底层方法调用校验失败,下面是具体的排查和解决步骤:

一、先分析核心原因

你提到单独用在注册或更新页面正常,但同时用两个场景就崩溃,结合ART的quick_trampoline_entrypoints.cc检查失败日志,主要可能是这几个问题:

  • Retrofit Service实例没有全局单例,两个场景各自创建实例导致OkHttpClient连接池/请求调度冲突
  • 注册和更新场景的Multipart请求参数构建逻辑不一致,触发Retrofit内部解析错误
  • 不同场景使用了不同配置的OkHttpClient,引发线程或资源冲突

二、具体解决方案

1. 确保Retrofit及Service实例全局单例

不要在注册页和更新页各自new Retrofit或Service实例,统一用单例管理:

public class RetrofitClient {
    private static Retrofit retrofit;
    private static final String BASE_URL = "你的接口域名";

    // 全局单例Retrofit实例
    private static Retrofit getInstance() {
        if (retrofit == null) {
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();

            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

    // 全局复用的文件上传Service
    public static FileUploadService getFileUploadService() {
        return getInstance().create(FileUploadService.class);
    }
}

注册和更新页面都通过RetrofitClient.getFileUploadService()获取Service实例,避免重复创建。

2. 统一Multipart请求构建逻辑

把注册和更新场景的Multipart参数构建抽成通用工具方法,避免参数遗漏或MediaType错误:

public static MultipartBody.Part buildFilePart(File file) {
    RequestBody fileBody = RequestBody.create(MediaType.parse("image/*"), file);
    return MultipartBody.Part.createFormData("avatar", file.getName(), fileBody);
}

public static RequestBody buildTextPart(String content) {
    return RequestBody.create(MediaType.parse("text/plain"), content);
}

两个场景调用同一套方法构建参数,比如注册时:

MultipartBody.Part avatarPart = buildFilePart(avatarFile);
RequestBody usernameBody = buildTextPart(username);
// 调用接口
RetrofitClient.getFileUploadService().registerUser(avatarPart, usernameBody);

更新时:

MultipartBody.Part avatarPart = buildFilePart(newAvatarFile);
RequestBody userIdBody = buildTextPart(userId);
// 调用接口
RetrofitClient.getFileUploadService().updateUserAvatar(avatarPart, userIdBody);

3. 规范Service接口方法

如果注册和更新的接口参数有差异,不要强行复用同一个接口方法,分开定义更清晰:

public interface FileUploadService {
    // 注册场景接口
    @Multipart
    @POST("user/register")
    Call<BaseResponse> registerUser(
            @Part MultipartBody.Part avatar,
            @Part("username") RequestBody username
    );

    // 更新资料场景接口
    @Multipart
    @POST("user/update/avatar")
    Call<BaseResponse> updateUserAvatar(
            @Part MultipartBody.Part avatar,
            @Part("user_id") RequestBody userId
    );
}

这样能避免因参数不匹配导致的底层方法调用校验失败。

4. 完善异常捕获与日志

在请求回调中打印完整异常栈,方便定位具体问题:

RetrofitClient.getFileUploadService()
        .registerUser(avatarPart, usernameBody)
        .enqueue(new Callback<BaseResponse>() {
            @Override
            public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
                // 处理成功逻辑
            }

            @Override
            public void onFailure(Call<BaseResponse> call, Throwable t) {
                // 打印完整异常信息
                t.printStackTrace();
                Log.e("UploadCrash", "请求失败详情", t);
            }
        });

5. 清理编译缓存

如果以上方法都无效,试试清理项目的build缓存(Android Studio中选File -> Invalidate Caches... -> Invalidate and Restart),有时候ART的错误是编译缓存导致的类文件不一致。

内容的提问来源于stack exchange,提问作者Nandita Dey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:12:48