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
相关产品推荐
相关产品推荐

