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

Android Kotlin中如何通过Multipart将JSON数据传入MVVM模型?

正确实现Android Kotlin中Multipart形式传递JSON数据到API(MVVM架构)

当前代码的核心问题

你的ViewModel中处理availabilities数组的方式存在错误:直接调用availabilities[i].toString()会生成类似com.yourpackage.AvailabilitiesModel@xxxxxx的非JSON格式字符串,后端无法解析该格式,导致接口无法正确识别数组数据。

正确实现步骤

1. 添加JSON序列化依赖

首先确保项目引入JSON序列化库(以常用的Gson为例),在Module级别的build.gradle中添加依赖:

dependencies {
    implementation 'com.google.code.gson:gson:2.10.1'
}

2. 修改ViewModel中的Multipart构建逻辑

将availabilities数组序列化为标准JSON字符串后,再作为FormData字段传入,同时优化代码结构:

private var updateRestaurantProfile = MutableLiveData<GetRestaurantDetailModel>()
fun getObserveUpdateRestaurantProfile() = updateRestaurantProfile

// 初始化Gson实例(放在ViewModel初始化阶段,避免重复创建)
private val gson = Gson()

fun updateRestaurantProfile(
    restaurantId: String,
    name: String,
    address: String,
    cityId: String,
    proviceId: String,
    countryId: String,
    availabilities: ArrayList<AvailabilitiesModel>
) {
    val builder = MultipartBody.Builder()
        .setType(MultipartBody.FORM)

    // 处理基础字段,保留原空值判断逻辑
    if (name.isNotEmpty()) {
        builder.addFormDataPart("name", name)
    }
    if (address.isNotEmpty()) {
        builder.addFormDataPart("address", address)
    }
    builder.addFormDataPart("cityId", cityId)
    builder.addFormDataPart("proviceId", proviceId) // 注意:若后端字段实际为provinceId需修正拼写
    builder.addFormDataPart("countryId", countryId)
    builder.addFormDataPart("restaurantId", restaurantId)

    // 正确序列化availabilities数组为JSON字符串
    if (availabilities.isNotEmpty()) {
        val availabilitiesJson = gson.toJson(availabilities)
        builder.addFormDataPart("availabilities", availabilitiesJson)
    }

    val requestBody = builder.build()

    // 优化Repository初始化逻辑(建议在ViewModel构造函数中初始化,避免重复判断)
    if (!this::repository.isInitialized) {
        repository = HomeRepository()
    }
    isLoading.value = true
    repository.updateRestaurantProfile(requestBody).observeForever { response ->
        isLoading.value = false
        if (response.status == ResponseStatus.SUCCESS) {
            updateRestaurantProfile.value = response.data
        } else {
            errorListener.value = response.status
        }
    }
}

3. 确保AvailabilitiesModel的序列化正确性

你的AvailabilitiesModel类需与JSON字段一一对应,Gson会自动完成映射,示例代码:

data class AvailabilitiesModel(
    val dayName: String,
    val isOpen: Int,
    val startTime: String,
    val endTime: String
)

若模型字段与JSON字段名不一致,可使用@SerializedName注解指定映射关系:

data class AvailabilitiesModel(
    @SerializedName("dayName") val dayName: String,
    @SerializedName("isOpen") val isOpen: Int,
    @SerializedName("startTime") val startTime: String,
    @SerializedName("endTime") val endTime: String
)

备选方案:按索引拆分传递数组元素(适配部分后端要求)

如果后端要求数组元素按索引拆分传递(如availabilities[0].dayName格式),可修改循环逻辑:

if (availabilities.isNotEmpty()) {
    availabilities.forEachIndexed { index, availability ->
        builder.addFormDataPart("availabilities[$index][dayName]", availability.dayName)
        builder.addFormDataPart("availabilities[$index][isOpen]", availability.isOpen.toString())
        builder.addFormDataPart("availabilities[$index][startTime]", availability.startTime)
        builder.addFormDataPart("availabilities[$index][endTime]", availability.endTime)
    }
}

这种方式需后端接口支持对应参数格式,优先推荐JSON字符串传递的方式,更简洁且兼容性更好。

额外优化建议

  • 在ViewModel构造函数中初始化repository,避免每次调用方法时重复判断。
  • 若Repository使用协程实现,建议用viewModelScope管理协程,避免observeForever可能引发的内存泄漏,或在合适时机手动移除观察者。

内容的提问来源于stack exchange,提问作者krunal almighty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 10:55:22