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
相关产品推荐
相关产品推荐

