嘿,我想从对象类调用api。我是新来的。我尝试了一些代码,但我不确定它是否正确。
我还得到了errorProcess:
com.dimen.app, PID: 12496
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)Session.kt
interface Session{
@DELETE("/session/delete")
fun deleteSession(): Call<Void>
}SessionRepository.kt
suspend fun deleteSession(): RequestResult<Void> {
return apiCall(api.deleteSession())
}RequestResult是密封级
sealed class RequestResult<out T : Any> {
data class Success<out T : Any>(): RequestResult<T>
data class Error(): RequestResult<Nothing>()
fun result(success: (data: T?) -> Unit),error: (error: Error) -> Unit)
}MainActivity.kt
private fun setupLogout() {
logoutButton.setOnClickListener {
LoginHelper.logout() // need to wait untill this finish
// more logic here....
}
}LoginHelper.kt
object LoginHelper {
fun logout() {
logD("logout")
deleteSession() // need to wait untill this finish and then excute more function....
}
private fun deleteSession() {
runBlocking{
apiCall.deleteSession().execute()
}
}
}发布于 2021-08-09 13:59:26
不要在安卓应用程序中使用runBlocking,除非你知道自己在做什么。99%的情况下,这是错误的选择,因为它违背了使用协同机制的目的。阻塞意味着当前线程等待协同线程运行其异步代码。但是您不能阻止主线程,因为这会冻结UI。
由于您的LoginHelper是object或单例,如果要启动协同服务,它需要自己的CoroutineScope。
您可以使deleteSession()成为一个挂起函数,这样它就可以调用api.deleteSession()挂起函数。
您可以让logout()启动一个协同线,以便依次删除会话并随后执行其他任务。您可以让它返回已启动的作业,以便其他类可以选择是简单地启动注销,还是在协同线中启动和等待注销。
object LoginHelper {
private val scope = CoroutineScope(SupervisorJob() + CoroutineName("LoginHelper"))
fun logout(): Job = scope.launch {
logD("logout")
deleteSession()
// .... more functions that happen after deleteSession() is complete
}
private suspend fun deleteSession() {
Tokenclass.getToken()?.let {
logE("token ::-> $it")
apiCall.deleteSession(it).execute()
}
}
}如果希望外部类能够等待logout完成,它可以在自己的协同线中调用返回的作业的join(),例如:
logoutButton.setOnClickListener {
lifecycleScope.launch {
LoginHelper.logout().join()
// more logic here....
}
}如果您不需要在活动中等待它,则不需要启动协同线,也不需要调用join()。
https://stackoverflow.com/questions/68712809
复制相似问题