You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin协程中两个挂起函数仅执行其一的问题解决求助

问题解决:挂起函数中仅第一个调用的挂起函数执行

问题核心原因

你遇到的问题根源是 getUserPosts 里的 watch().collect() 会永久挂起当前协程。watch() 返回的是持续监听GraphQL数据更新的Flow,collect 会一直停留在该语句等待新数据发射,永远不会走到 Finished 3,导致 getContent 里的第二个函数 getRecentPosts 完全没机会执行。


解决方案

根据你的业务需求,有两种处理方式:

1. 仅获取单次数据(不需要实时更新)

把 watch() 替换为 execute(),它会发起单次请求并返回响应,函数执行完成后会正常结束,不会阻塞后续代码:

override suspend fun getUserPosts(token: String) {
    try {
        myInterceptor.setAccessToken(token)
        // 用execute()替换watch(),获取单次响应
        val response = graphqlAPI.query(GetUserPostsQuery())
            .fetchPolicy(FetchPolicy.NetworkFirst)
            .execute()

        val newList = arrayListOf<Post>()
        response.data?.getUserPosts?.let {
            for (post in it) {
                newList.add(
                    Post(
                        id = post.postFragment.id,
                        ...
                    )
                )
            }
            userState.editUserState(userState.userStateFlow.value?.copy(posts = newList))
            Log.i("#+#", "Finished 1")
        }
        Log.i("#+#", "Finished 2")
        Log.i("#+#", "Finished 3")
    } catch (e: ApolloException) {
        e.printStackTrace()
    }
}

2. 需要持续监听实时数据

如果要保留实时监听能力,需要把 collect 放到单独的协程中执行,让 getUserPosts 能正常返回,不阻塞后续代码:

方式一:在挂起函数内部启动独立协程

override suspend fun getUserPosts(token: String) {
    try {
        myInterceptor.setAccessToken(token)
        val postsFlow = graphqlAPI.query(GetUserPostsQuery())
            .fetchPolicy(FetchPolicy.NetworkFirst)
            .watch()

        // 用viewModelScope启动独立协程收集Flow,不阻塞当前函数
        viewModelScope.launch {
            postsFlow.collect { response ->
                val newList = arrayListOf<Post>()
                response.data?.getUserPosts?.let {
                    for (post in it) {
                        newList.add(
                            Post(
                                id = post.postFragment.id,
                                ...
                            )
                        )
                    }
                    userState.editUserState(userState.userStateFlow.value?.copy(posts = newList))
                    Log.i("#+#", "Finished 1")
                }
                Log.i("#+#", "Finished 2")
            }
        }
        Log.i("#+#", "Finished 3")
    } catch (e: ApolloException) {
        e.printStackTrace()
    }
}

方式二:在getContent中并行启动两个函数

直接在 getContent 里用 launch 分别启动两个挂起函数,让它们并行执行,互不阻塞:

override suspend fun getContent(token: String) {
    // 并行启动两个协程,各自执行对应的挂起函数
    viewModelScope.launch {
        getUserPosts(token)
    }
    viewModelScope.launch {
        getRecentPosts(token)
    }
}

内容的提问来源于stack exchange,提问作者HavanaSun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:30:32