如何解决API 调用期间的 Android 屏幕旋转会导致 kotlinx.coroutines.JobCancellationException
我收到此错误 -
System.err: kotlinx.coroutines.JobCancellationException: StandaloneCoroutine was cancelled; job=StandaloneCoroutine{Cancelling}
这是我的片段代码 -
@AndroidEntryPoint
class LoginView : Fragment(R.layout.login_view) {
private val viewModel by viewModels<LoginViewModel>()
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
view.login_button.setOnClickListener {
val email = view.email_input_layout.text.toString()
val password = view.password_input_layout.text.toString()
viewModel.loginUser(email,password).observe(viewLifecycleOwner,{
// ….
})
}
}
}
这是我的 ViewModel 代码 -
fun loginUser(email: String,password: String)= repo.loginUser(Action.LoginUser(email,password)).map {
when (it) {
// …
}
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
这是回购代码 -
fun loginUser(action: Action) = flow {
when (action) {
is Action.LoginUser -> {
emit(Result.Loading)
val result = remoteSource.loginUser(LoginModel(action.email,action.password))
emit(result)
}
}
}
这里是远程数据源代码 -
override suspend fun loginUser(loginModel: LoginModel): Result {
try {
Log.e(TAG,“Going to do api call" + Thread.currentThread().name)
val result = withContext(Dispatchers.IO) {
Log.e(TAG,“Doing api call" + Thread.currentThread().name)
apiInterface.loginUser(loginModel)
}
if (result.isSuccessful) {
Log.e(TAG,“Api call success")
return Result.Success(result.body())
} else {
Log.e(TAG,“Api call error”)
return Result.Error(result.code())
}
} catch (e: Exception) {
// Here I catch the JobCancellationException
e.printStackTrace()
}
return Result.Error(UNKNOWN_ERROR)
}
最后是 Api 接口 -
@POST("login")
suspend fun loginUser(@Body loginModel: LoginModel): Response<LoginResponseModel>
我模拟了要在 20 秒内交付的 API 响应。
问题来了——
我点击了登录按钮,登录调用正在发生。现在我看到了日志 -
Going to do api call main
Doing api call DefaultDispatcher-worker-1
如您所见,我一直在 main
线程上,直到请求调用并且在我进行调用时发生线程切换。
现在我在 API 调用的中间旋转手机,我的视图创建了新的,这是预期的,我没有看到任何日志,几秒钟内我得到了 JobCancellationException
,我在 { {1}}。谁能指导我这里的错误究竟是什么
解决方法
好的,我解决了问题 -
这是我的视图模型 -
var loginViewState: LiveData<LoginViewState> = MutableLiveData()
fun loginUser(email: String,password: String) {
loginViewState = repo.loginUser(Action.LoginUser(email,password)).map {
// Do the mapping
}.asLiveData(Dispatchers.Default + viewModelScope.coroutineContext)
}
我的 Fragment 看起来像这样 -
@AndroidEntryPoint
class LoginView : Fragment(R.layout.login_view) {
private val viewModel by viewModels<LoginViewModel>()
override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
super.onViewCreated(view,savedInstanceState)
view.login_button.setOnClickListener {
val email = view.email_input_layout.text.toString()
val password = view.password_input_layout.text.toString()
viewModel.loginUser(email,password)
viewModel.loginViewState.observe(viewLifecycleOwner,{
// …
})
}
viewModel.loginViewState.observe(viewLifecycleOwner,{
// …
})
}
}
所以解决方案是使用一个变量并观察它的变化。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。