Kotlin Coroutine结合MVVM的首个登录应用运行失败,求排查代码错误
代码问题排查及修复方案
问题1:LoginViewModel 方法修饰错误、无结果通知逻辑
login方法被错误加上suspend修饰符,内部已经通过viewModelScope.launch启动协程,对外暴露的方法不需要挂起修饰。另外你创建的Resource实例没有通过可观察对象通知UI层,UI无法拿到请求结果。
修复代码:class LoginViewModel (private val loginRepository: LoginRepository) : ViewModel() { // 用LiveData向外发送登录结果,也可根据需求替换为StateFlow private val _loginResult = MutableLiveData<Resource<LoginResponse>>() val loginResult: LiveData<Resource<LoginResponse>> = _loginResult // 移除suspend修饰 fun login(email: String, password: String) { viewModelScope.launch { try { val loginModel = LoginModel(email, password) val response = loginRepository.login(loginModel) if (response.isSuccessful) { response.body()?.let { _loginResult.postValue(Resource.success(data = it)) } ?: _loginResult.postValue(Resource.error(data = null, message = "登录响应为空")) } else { // 解析接口返回的错误信息 val error = Gson().fromJson(response.errorBody()?.string(), LoginError::class.java) _loginResult.postValue(Resource.error(data = null, message = error.error ?: "登录失败")) } } catch (ex: Exception) { _loginResult.postValue(Resource.error(data = null, message = ex.message ?: "请求出错")) } } } }问题2:API接口缺少登录请求参数
你构造了携带账号密码的LoginModel,但全程没有传给API接口,后台收不到登录参数必然返回错误。
修复代码:interface Api { @POST("login") // 增加@Body注解传递登录参数 suspend fun makeLogin(@Body loginModel: LoginModel): Response<LoginResponse> }问题3:ApiHelper、Repository层参数传递缺失
两层的方法都没有接收LoginModel参数,导致参数无法传递到API层。
修复代码:class ApiHelper (private val api: Api) { // 增加LoginModel入参 suspend fun makeLogin(loginModel: LoginModel) = api.makeLogin(loginModel) } class LoginRepository(private val apiHelper: ApiHelper) { // 修正命名贴合业务,传递参数到ApiHelper suspend fun login(loginModel: LoginModel) = apiHelper.makeLogin(loginModel) }问题4:ViewModelFactory 缺少类闭合大括号
现有代码中类定义缺少闭合的},会直接导致编译失败。
修复代码:class ViewModelFactory (private val apiHelper: ApiHelper) : ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(LoginViewModel::class.java)) { return LoginViewModel(LoginRepository(apiHelper)) as T } throw IllegalArgumentException("Unknown class name") } // 补全类的闭合大括号 }额外规范建议
- 后续业务层方法命名尽量贴合实际逻辑,不要用
getUsers这类和登录功能不符的命名 - 可以把Response的错误解析逻辑封装为扩展方法,减少重复代码
- UI层直接观察
loginResult即可拿到登录结果,做对应的 toast 、页面跳转等交互处理
- 后续业务层方法命名尽量贴合实际逻辑,不要用
内容的提问来源于stack exchange,提问作者user15272114
相关产品推荐
相关产品推荐

