Неверно отображается порядок вывода - PullRequest
2 голосов
/ 11 апреля 2019

У меня очень странная проблема. У меня есть список hashmap (groupList) в FragemtA. Каждый раз, когда fragmentA запускается, он должен вызывать функцию checkUser и, наконец, получить возвращаемое значение на forEach там.

    var id = ""

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)

            val userId = checkUser()

            activity.groupedList.forEach {
                for (i in it.value) {
                    Log.d(TAG, "user id in groupedList" + userId)
                }
        }

fun checkUser(): String {
        GlobalScope.launch(Dispatchers.Main) {
            val response = WebApi.getOrganizationsList(activity)
            if (response?.status == "success") {
                id = response?.user_id.toString()
                Log.d(TAG,"id in checkUser "+id)
            } else {
                longToast("FAIL")
            }
        }
        return id
    }

Почему я получу этот вывод?

D/xxx: user id in groupedList
D/xxx: user id in groupedList
D/xxx: id in checkUser 46

Я бы ожидал, что сначала отобразится id in checkUser 46, но это не так!

Желаемый выход

D/xxx: id in checkUser 46
D/xxx: user id in groupedList 46
D/xxx: user id in groupedList 46

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

Вы запускаете поток, но не ожидаете его завершения. Измените это, чтобы ждать, и вы будете в порядке. Кстати, использование GlobalScope обычно не рекомендуется. Вам следует подумать о реализации CoroutineScope в своем классе, чтобы вы могли просто использовать ключевое слово «запуск».

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        GlobalScope.launch {
            val userId = checkUser()

            activity.groupedList.forEach {
                for (i in it.value) {
                    Log.d(TAG, "user id in groupedList" + userId)
                }
        }
    }

suspend fun checkUser(): String = suspendCoroutine { c->
        GlobalScope.launch(Dispatchers.Main) {
            var id = ""
            val response = WebApi.getOrganizationsList(activity)
            if (response?.status == "success") {
                id = response?.user_id.toString()
                Log.d(TAG,"id in checkUser "+id)
            } else {
                longToast("FAIL")
            }
            c.resume(id)
        }
    }
1 голос
/ 11 апреля 2019

Во-первых, вашей сопрограмме не нужно возвращать строку, поскольку вы уже сохраняете ее результат в свойстве id.

Во-вторых, сообщение, которое вы ожидаете стать первым, является последним, потому что запускаемая вами сопрограмма завершает выполнение позже, чем цикл - ко времени выполнения цикла forEach сопрограмма еще не завершилась. еще. Вы должны помнить, что ваш код не будет выполняться последовательно, потому что вы не ожидаете завершения сопрограммы.

Один из вариантов - выполнить ваше действие (т. Е. Цикл forEach) внутри сопрограммы, если вы уверены, что значение идентификатора уже получено успешно:

fun checkUser() {
    GlobalScope.launch(Dispatchers.Main) {
        val response = WebApi.getOrganizationsList(activity)
        if (response?.status == "success") {
            id = response?.user_id.toString()
            Log.d(TAG,"id in checkUser "+id)
            activity.groupedList.forEach {
                for (i in it.value) {
                    Log.d(TAG, "user id in groupedList" + id)
                }
            }
        } else {
            longToast("FAIL")
        }
    }
}
...