Kotlin中基于MVVM架构,用Data Class+Retrofit+Moshi实现POST请求
MVVM架构下数据提交到服务端的适配方案
1. UI层能否直接访问data包的RegisterLoginDataModel?
不建议直接访问。RegisterLoginDataModel是和服务端接口强绑定的(带有@Json注解),UI层直接依赖它会导致UI与服务端耦合度过高——一旦服务端字段变更,UI层代码也要同步修改,违背了MVVM分层解耦的核心原则。
2. 正确的分层处理步骤
按照MVVM的职责划分,需要拆分出UI层表单模型、(可选)domain层业务模型,再通过ViewModel完成各层模型的转换:
步骤1:创建UI层表单模型(UI包下)
这个类只负责收集用户输入,字段命名贴合UI场景,无需和服务端字段绑定:
// ui包下的RegisterFormState data class RegisterFormState( val gender: String?, val goal: String?, val targetWeight: String?, val currentWeight: String?, val targetHeight: String?, val currentHeight: String?, val birthday: String?, val email: String?, val username: String?, val password: String? )
步骤2:(可选)创建domain层业务模型(domain包下)
如果有复杂的业务校验、数据预处理需求,在domain层定义业务模型,承载经过业务处理后的数据(可将字段设为非空,保证业务合规性):
// domain包下的RegisterUser data class RegisterUser( val gender: String, val goal: String, val targetWeight: String, val currentWeight: String, val targetHeight: String, val currentHeight: String, val birthday: String, val email: String, val username: String, val password: String )
步骤3:ViewModel中完成模型转换与请求发起
ViewModel作为中间层,接收UI层的表单数据,完成校验、模型转换后,通过Retrofit发起请求:
// ViewModel类 class RegisterViewModel : ViewModel() { private val apiService = RetrofitClient.getApiService() fun submitRegisterForm(formState: RegisterFormState) { // 1. UI输入校验(非空、格式等) if (formState.username.isNullOrEmpty() || formState.password.isNullOrEmpty()) { // 通知UI校验失败(比如通过LiveData发送事件) return } // 2. 转换为domain业务模型(可选) val registerUser = RegisterUser( gender = formState.gender ?: "", goal = formState.goal ?: "", targetWeight = formState.targetWeight ?: "", currentWeight = formState.currentWeight ?: "", targetHeight = formState.targetHeight ?: "", currentHeight = formState.currentHeight ?: "", birthday = formState.birthday ?: "", email = formState.email ?: "", username = formState.username ?: "", password = formState.password ?: "" ) // 3. 转换为data层请求模型 val requestModel = RegisterLoginDataModel( userGender = registerUser.gender, userGoal = registerUser.goal, userTargetWeight = registerUser.targetWeight, userCurrentWeight = registerUser.currentWeight, userTargetHeight = registerUser.targetHeight, userCurrentHeight = registerUser.currentHeight, userBirthDay = registerUser.birthday, userMail = registerUser.email, userName = registerUser.username, userPassword = registerUser.password ) // 4. 发起Retrofit请求 viewModelScope.launch { try { val response = apiService.register(requestModel) // 处理成功响应,通知UI } catch (e: Exception) { // 处理异常,通知UI } } } }
步骤4:UI层调用ViewModel提交方法
UI层(Activity/Fragment)仅维护自身表单状态,点击提交时将状态传给ViewModel即可:
// Fragment示例代码 binding.btnRegister.setOnClickListener { val formState = RegisterFormState( gender = binding.etGender.text.toString(), goal = binding.etGoal.text.toString(), targetWeight = binding.etTargetWeight.text.toString(), currentWeight = binding.etCurrentWeight.text.toString(), targetHeight = binding.etTargetHeight.text.toString(), currentHeight = binding.etCurrentHeight.text.toString(), birthday = binding.etBirthday.text.toString(), email = binding.etEmail.text.toString(), username = binding.etUsername.text.toString(), password = binding.etPassword.text.toString() ) viewModel.submitRegisterForm(formState) }
3. 简化场景的特殊处理
如果项目业务逻辑极简单,无复杂校验或预处理,可跳过domain层,直接在ViewModel中完成UI表单模型到data请求模型的转换,但仍需避免UI层直接引用data层的RegisterLoginDataModel,防止耦合。
内容的提问来源于stack exchange,提问作者NewPartizal
相关产品推荐
相关产品推荐

