Kotlin Coroutines:作业调度问题。(invokeOnCompletion)
Kotlin Coroutines: Issue with job-scheduling.(invokeOnCompletion)
我对这个 kotlin-coroutine 东西还很陌生,我对 job-scheduling.In 下面的代码有疑问,首先我从片段中的用户缓存中获取主题名称。(topicsList)
然后,我需要从 API 中一个一个地获取这些主题。我想要做的是遍历 topicsList,为每个主题发出请求,并在所有请求完成后获得所有响应。为了实现这一点,在 getEverything() 方法(触发请求)中,我每次都将响应添加到数组列表中。(responseList)
在 for 循环中,我启动了所有请求。作业完成后,调用 job.invokeOnCompletion{} 并将我的 liveData 设置为 responseList。但是,这种方法不起作用。问题是,我在设置 responseList 之前更新 liveData。我不知道这怎么可能。有人可以帮我解决这个问题吗?
这是我在 myFragment 中的 CoroutineScope:
val topicsList = dataMap["topics"] // GOT THE TOPICS
topicsList?.let {
var job: Job
CoroutineScope(Dispatchers.Main).launch {
job = launch {
for (topic in topicsList) {
mViewModel.getEverything(topic, API_KEY)
}
}
job.join()
job.invokeOnCompletion {
mViewModel.updateLiveData()
}
}
} ?: throw Exception("NULL")
viewModel 中的 getEverything() 方法:
suspend fun getEverything(topic: String, apiKey: String) {
viewModelScope.launch {
_isLoading.value = true
withContext(Dispatchers.IO) {
val response = api.getEverything(topic, apiKey)
withContext(Dispatchers.Main) {
if (response.isSuccessful) {
if (response.body() != null) {
responseList.add(response.body()!!)
println("Response is successful: ${response.body()!!}")
_isLoading.value = false
_isError.value = false
}
}
else {
Log.d(TAG, "getEverything: ${response.errorBody()}")
_isError.value = true
_isLoading.value = false
}
}
}
}
}
以及 updateLiveData 方法:
fun updateLiveData() {
_newsResponseList.value = responseList
println("response list : ${responseList.size}")
responseList.clear()
}
这是它在日志中的样子:Logs
给打不开图片的你记录一下:
I/System.out: response list : 0
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=wired, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=techcrunch, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=wired, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=the-verge, ...
顺便说一句,数据获取没有错误而且是正确的。我对此没有意见。
问题是 getEverything
使用 launch
创建后台作业,然后 return 秒才知道作业完成。
要解决此问题,请直接获取 getEverything
return 数据:
suspend fun getEverything(topic: String, apiKey: String): Response? {
_isLoading.value = true
val response = withContext(Dispatchers.IO) {
api.getEverything(topic, apiKey)
}
_isLoading.value = false
return response.takeIf { it.isSuccessful }?.body()?.let { body ->
println("Response is successful: $body")
}.also {
_isError.value = it == null
}
}
在您的片段中,请求结果并分配它们:
lifecycleScope.launch {
_responseList.value = topicsList.mapNotNull { topic ->
model.getResponse(topic, apiKey)
}
}
我对这个 kotlin-coroutine 东西还很陌生,我对 job-scheduling.In 下面的代码有疑问,首先我从片段中的用户缓存中获取主题名称。(topicsList) 然后,我需要从 API 中一个一个地获取这些主题。我想要做的是遍历 topicsList,为每个主题发出请求,并在所有请求完成后获得所有响应。为了实现这一点,在 getEverything() 方法(触发请求)中,我每次都将响应添加到数组列表中。(responseList) 在 for 循环中,我启动了所有请求。作业完成后,调用 job.invokeOnCompletion{} 并将我的 liveData 设置为 responseList。但是,这种方法不起作用。问题是,我在设置 responseList 之前更新 liveData。我不知道这怎么可能。有人可以帮我解决这个问题吗?
这是我在 myFragment 中的 CoroutineScope:
val topicsList = dataMap["topics"] // GOT THE TOPICS
topicsList?.let {
var job: Job
CoroutineScope(Dispatchers.Main).launch {
job = launch {
for (topic in topicsList) {
mViewModel.getEverything(topic, API_KEY)
}
}
job.join()
job.invokeOnCompletion {
mViewModel.updateLiveData()
}
}
} ?: throw Exception("NULL")
viewModel 中的 getEverything() 方法:
suspend fun getEverything(topic: String, apiKey: String) {
viewModelScope.launch {
_isLoading.value = true
withContext(Dispatchers.IO) {
val response = api.getEverything(topic, apiKey)
withContext(Dispatchers.Main) {
if (response.isSuccessful) {
if (response.body() != null) {
responseList.add(response.body()!!)
println("Response is successful: ${response.body()!!}")
_isLoading.value = false
_isError.value = false
}
}
else {
Log.d(TAG, "getEverything: ${response.errorBody()}")
_isError.value = true
_isLoading.value = false
}
}
}
}
}
以及 updateLiveData 方法:
fun updateLiveData() {
_newsResponseList.value = responseList
println("response list : ${responseList.size}")
responseList.clear()
}
这是它在日志中的样子:Logs
给打不开图片的你记录一下:
I/System.out: response list : 0
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=wired, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=techcrunch, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=wired, ...
I/System.out: Response is successful: NewsResponse(articleList=[Article(source=Source(id=the-verge, ...
顺便说一句,数据获取没有错误而且是正确的。我对此没有意见。
问题是 getEverything
使用 launch
创建后台作业,然后 return 秒才知道作业完成。
要解决此问题,请直接获取 getEverything
return 数据:
suspend fun getEverything(topic: String, apiKey: String): Response? {
_isLoading.value = true
val response = withContext(Dispatchers.IO) {
api.getEverything(topic, apiKey)
}
_isLoading.value = false
return response.takeIf { it.isSuccessful }?.body()?.let { body ->
println("Response is successful: $body")
}.also {
_isError.value = it == null
}
}
在您的片段中,请求结果并分配它们:
lifecycleScope.launch {
_responseList.value = topicsList.mapNotNull { topic ->
model.getResponse(topic, apiKey)
}
}