【发布时间】:2021-11-28 02:50:50
【问题描述】:
我正在尝试理解 Kotlin couroutine。所以这是我的代码(基于this tutorial)。为了保持代码相对简单,我特意避免使用 MVVM、LiveData 等。只使用 Kotlin couroutine 和 Retrofit。
考虑这个登录过程。
ApiInterface.kt
interface ApiInterface {
// Login
@POST("/user/validate")
suspend fun login(@Body requestBody: RequestBody): Response<ResponseBody>
}
ApiUtil.kt
class ApiUtil {
companion object {
var API_BASE_URL = "https://localhost:8100/testApi"
fun getInterceptor() : OkHttpClient {
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
return okHttpClient
}
fun createService() : ApiInterface {
val retrofit = Retrofit.Builder()
.client(getInterceptor())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(OJIRE_BASE_URL)
.build()
return retrofit.create(ApiInterface::class.java)
}
}
fun login(userParam: UserParam): String {
val gson = Gson()
val json = gson.toJson(userParam)
var resp = ""
val requestBody = json.toString().toRequestBody("application/json".toMediaTypeOrNull())
CoroutineScope(Dispatchers.IO).launch {
val response = createService().login(requestBody)
withContext(Dispatchers.Main){
if (response.isSuccessful){
val gson = GsonBuilder().setPrettyPrinting().create()
val prettyJson = gson.toJson(
JsonParser.parseString(
response.body()
?.string()
)
)
resp = prettyJson
Log.d("Pretty Printed JSON :", prettyJson)
}
else {
Log.e("RETROFIT_ERROR", response.code().toString())
}
}
}
return resp
}
}
LoginActivity.kt
class LoginActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
edtUsername = findViewById(R.id.edtUsername)
edtPassword = findViewById(R.id.edtPassword)
btnLogin = findViewById(R.id.btnLogin)
btnLogin.setOnClickListener {
val api = ApiUtil()
val userParam = UserParam(edtMobileNo.text.toString(), edtPassword.text.toString())
val response = JSONObject(api.login(userParam))
var msg = ""
if (response.getString("message").equals("OK")){
msg = "Login OK"
}
else {
msg = "Login failed"
}
Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT).show()
}
}
}
调试登录活动时,API 响应在prettyJson 上正确捕获
问题是resp 仍然是空的。猜猜这就是异步进程的工作方式。我想要的是等到API调用完成,然后结果可以很好地传递给resp作为login()的返回值。该怎么做?
【问题讨论】:
-
您可以使用 resp:(String) -> Unit 作为 login() 函数中的额外参数,并在响应后在视图中捕获该参数(在 Activity 中)
标签: android kotlin kotlin-coroutines kotlin-android-extensions