在尝试将 Jetpack Compose 与 OKHttp 结合使用时,我正在发出一个 HTTP 请求,当它返回时(如果成功)我想启动一个新活动,否则向用户显示一条 toast 错误消息。
但是,我不确定实际上如何
startActivity
。我收到以下错误:
fun performLogin(loginViewModel: LoginViewModel, context: Context) {
try {
val email = loginViewModel.email.value
val password = loginViewModel.password.value
val client = OkHttpClient()
val serverUri = SystemService.getAPIUri()
val loginUri = "$serverUri/login"
val data = """
"email": "$email",
"password": "$password"
""".trimIndent()
val formBody = FormBody.Builder()
.add("email", email.toString())
.add("password", password.toString())
.build()
val body = data.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
val request = Request.Builder()
.url(loginUri)
.post(formBody)
.build()
val call = client.newCall(request)
call.enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
for ((name, value) in response.headers) {
println("$name: $value")
}
println(response.body!!.string())
Looper.prepare()
// Gives an error here
loginCallback()
Looper.loop()
}
}
})
} catch (e: Exception) {
println("Login Error: ")
println(e)
val toast = Toast.makeText(context, "Error Logging In", Toast.LENGTH_LONG)
toast.show()
}
}
@Composable
fun loginCallback() {
val context = LocalContext.current
context.startActivity(Intent(context, MainActivity::class.java))
}
如果出现 HTTP 错误,toast 将会崩溃,提示我必须在主线程中运行它。
并且调用 loginCallback() 不起作用,正如它所说的
@Composable invocations can only happen from the context of a @Composable function
由于 onResponse 不在可组合范围内,因此在 .enqueue(...) 之外声明
val coroutineScope = rememberCoroutineScope()
并在 coroutineScope.launch { }
内启动所需的代码,Toast.makeText(...) 也是如此。
尝试在 Kotlin 中使用函数作为参数,将 ViewModel 中的 toast 函数传递给 OKhttp 客户端,并在 onResponse 或 onFailure 中使用该函数作为回调
fun toast(msg:String){
displayToast(msg)
}
fun performLogin(loginViewModel: LoginViewModel, context: Context, displayToast:
(String) -> Unit) {
....
override fun onResponse(call: Call, response: Response) {
displayToast("Msg you want to display")
}
}