Android(Kotlin)-如何等待异步任务完成?

时间:2018-08-31 23:14:23

标签: android kotlin android-asynctask async-await httprequest

我是Android和Kotlin的新手,目前正在研究集中式API路由器类。 为此,我使用了Fuel Framework。 对于doAsync函数,我使用Anko for Kotlin库。

要从API检索授权令牌,我目前使用此方法:

 private fun Login(username: String, password: String, callback: (Map<Boolean, String>) -> Unit) {

        "/auth/token.json".httpPost()
                .header(mapOf("Content-Type" to "application/json"))
                .body("""{"username":"$username", "password":"$password"}""", Charsets.UTF_8)
                .response { request, response, result ->
                    request.headers.remove("Accept-Encoding")
                    when (result) {
                        is Result.Failure -> {

                            // val data = result.get()
                            val ex = result.getException()
                            val serverResponseJson = response.data.toString(Charsets.UTF_8)
                            var exceptionMessage = ex.message

                            val jelement = JsonParser().parse(serverResponseJson)
                            val jobject = jelement.asJsonObject

                            val serverResponseError = if (jobject.has("Error")) jobject.get("Error").asString else jobject.get("detail").asString


                            callback(mapOf(Pair(false, serverResponseError)))
                        }
                        is Result.Success -> {
                            val data = result.get()
                            val returnJson = data.toString(Charsets.UTF_8)
                            Log.println(Log.ASSERT, "RESULT_LOGIN", returnJson)

                            callback(mapOf(Pair(true, returnJson)))
                        }
                    }


                }
    }

我在

处调用此登录方法
val btnLogin = findViewById<Button>(R.id.btn_login)
    btnLogin.setOnClickListener { _ ->

        doAsync {
            val username = findViewById<EditText>(R.id.input_username_login)
            val password = findViewById<EditText>(R.id.input_password_login)

            Login(username.text.toString(), password.text.toString()) {

                // Request was successful
                if (it.containsKey(true)) {
                    // Parse return Json
                    // e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
                    val jelement = JsonParser().parse(it.getValue(true))
                    val jobject = jelement.asJsonObject

                    // save field for class-scope access
                    Constants.token = jobject.get("token").asString
                    Constants.id = jobject.get("id").asString
                }
                else{
                    Toast.makeText(this@LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
                }
            }
        }[30, TimeUnit.SECONDS]

         var test = Constants.id;

    }

在单独的Constants类中,我像这样存储令牌和ID:

class Constants {
    companion object {
        val baseUrl: String = "BASE_URL_TO_MY_API"

        val contentTypeJson = "application/json"

        lateinit var STOREAGE_PATH: String

        // current user details
        lateinit var id: String
        lateinit var token: String
        lateinit var refresh_token: String

        // logged in User
        lateinit var user: User
    }

如何确保在异步任务完成后设置测试变量?目前,我遇到了

  

lateinit属性ID尚未初始化

我遇到了将任务限制为超时的选项,例如我对 [30,TimeUnit.SECONDS] 所做的操作,很遗憾,这没有帮助。

感谢您的帮助!干杯。

1 个答案:

答案 0 :(得分:0)

我认为问题出在您要访问结果的位置:

val btnLogin = findViewById<Button>(R.id.btn_login)
btnLogin.setOnClickListener { _ ->

       doAsync {
        val username = findViewById<EditText>(R.id.input_username_login)
        val password = findViewById<EditText>(R.id.input_password_login)

        var test: String? = null

        Login(username.text.toString(), password.text.toString()) {

            // Request was successful
            if (it.containsKey(true)) {
                // Parse return Json
                // e.g. {"id":"36e8fac0-487a-11e8-ad4e-c471feb11e42","token":"d6897a230fd7739e601649bf5fd89ea4b93317f6","expiry":"2018-04-27T17:49:48.721278Z"}
                val jelement = JsonParser().parse(it.getValue(true))
                val jobject = jelement.asJsonObject

                // save field for class-scope access
                Constants.token = jobject.get("token").asString
                Constants.id = jobject.get("id").asString
            }
            else{
                Toast.makeText(this@LoginActivity, it.getValue(false), Toast.LENGTH_SHORT).show()
            }
        }

        test = Constants.id // here test variable surely set if result was successful, otherwise it holds the null value
        test?.let{
            resultDelivered(it)
        }

    }[30, TimeUnit.SECONDS]

}

fun resultDelivered(id: String){
    // here we know that the async job has successfully finished
}