我正在根据从API获得的大量数据制作一款应用程序.在显示实际的应用程序之前,我需要这些信息,所以我将负责获取这些信息的代码放在加载屏幕上.我将所有信息保存在一个本地数据库(Room数据库)中,这样我就不必在每次启动应用程序时都获取它(因为API没有太大变化),所以我可以实际使用这些信息.
1st problem :当我try 我的代码时,它保存了两次(或更多)对象(可能是因为Coroutines).由于我将fetch是否结束基于many saves happened / number of results,这会导致Activity认为fetch已经完成,停止所有调用.这意味着有些物体没有时间保存.
以下是我的代码(简化):
class FetchFromAPI {
fun fetchObjects(save: (Object) -> Unit) {
//Get number objects from API call
val count = API.getCount()
//Calculate number of pages
val limit = 100
var pageCount = count / limit
if (count % limit != 0) pageCount++
//For each page
for (i in 1..pageCount) {
CoroutineScope(Dispatchers.IO).launch {
//Get page
val page = API.getPage(i)
//Save objects from page
savePage(page, save)
}
}
}
private fun savePage(
page: JSONArray,
save: (Object) -> Unit
) {
//For each object in page
for (i in 0..page.length()) {
CoroutineScope(Dispatchers.IO).launch {
//Get object
val obj = page.getJSONObject(i)
//Save object
saveObject(obj, save)
}
}
}
private fun saveObject(
obj: JSONObject,
save: (Object) -> Unit
) {
//Convert Json to Object
...
save(obj)
}
}
saveObject(obj)
是一个函数,它将对象保存在Room数据库中,并更新获取进度(由流控制).
所以我在谷歌上搜索了一下,找到了关于JOBS和runBlocking{}
的大约join()
个信息,我想"我不需要确切的进度数字,因为它是用ProgressBar显示的,而且我正在处理数千个对象,所以如果我能知道我所有的协程程序什么时候都完成了,并基于这个而不是进度来返回调用,我就很好(即使多个调用浪费了一些资源)."
2nd problem :当我try 使用runBlocking{}
or join()
,这样我就可以启动一个函数,告诉我它已经完成了,该函数要么给我一个"应用程序被冻结"的错误,要么根本不启动.
我的代码已更改(简化):
class FetchFromAPI {
fun fetchObjects(save: (Object) -> Unit) {
//Get number objects from API call
val count = API.getCount()
//Calculate number of pages
val limit = 100
var pageCount = count / limit
if (count % limit != 0) pageCount++
runBlocking {
//For each page
for (i in 1..pageCount) {
launch {
//Get page
val page = API.getPage(i)
//Save objects from page
savePage(page, save)
}
}
}
}
private fun savePage(
page: JSONArray,
save: (Object) -> Unit
) {
//For each object in page
runBlocking {
for (i in 0..page.length()) {
launch {
//Get object
val obj = page.getJSONObject(i)
//Save object
saveObject(obj, save)
}
}
}
}
private fun saveObject(
obj: JSONObject,
save: (Object) -> Unit
) {
//Convert Json to Object
...
save(obj)
}
}
fun fetchingFromAPI(onFinished: () -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
fetchObjects(::save)
onFinished()
}
}
是不是有什么我不明白的地方,关于科鲁廷,join()
和runBlocking{}
?
如果你还需要我的代码里的任何东西,请告诉我.