Android (Kotlin) - Как мне ждать завершения асинхронной задачи? - PullRequest
0 голосов
/ 01 сентября 2018

Я новичок в Android и Kotlin и в настоящее время работаю над классом централизованного API-маршрутизатора. Для этого я использую Fuel Framework . Для функции doAsync я использую библиотеку Anko для 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 я храню токен и идентификатор следующим образом:

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 не был инициализирован

Я сталкивался с возможностью ограничить задачу тайм-аутом, как я сделал с [30, TimeUnit.SECONDS] , к сожалению, это не помогло.

Спасибо за помощь! Приветствия.

1 Ответ

0 голосов
/ 02 сентября 2018

Я думаю, проблема в том, где вы хотите получить доступ к результату:

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
}
...