输出顺序显示错误

时间:2019-04-11 14:42:26

标签: android kotlin retrofit coroutine

我遇到一个非常奇怪的问题。我在FragemtA中有一个哈希表列表(groupList)。每次运行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 个答案:

答案 0 :(得分:2)

您正在启动线程,但不等待其完成。更改它以等待,您会没事的。顺便说一句,通常不建议使用GlobalScope。您应该考虑在您的类上实现CoroutineScope,以便可以简单地使用关键字“ launch”。

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 :(得分:1)

首先,协程不需要返回字符串,因为您已经将其结果保存在属性id中。

第二,您希望成为第一条消息的消息是最后一条消息,因为您要启动的协程在循环执行之后执行完毕–到forEach循环运行时,协程还没有执行还没完成。您必须记住,由于您没有等待协程完成,因此代码不会顺序执行。

一种选择是在确定成功检索到ID值之后,在协程中执行操作(即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")
        }
    }
}