摆脱嵌套的任务类型

Getting rid of nested Task type

是否可以摆脱嵌套的任务泛型?

对于每个 continueWith 语句,都会在类型中添加一个新的 Task。每个延续都是类型的一部分。理想情况下,我会 return 一个任务,它连续执行每一个任务并作为一个任务成功或失败。

例子

第一个操作查询用户的组

private fun getGroupsSnapshot(): Task<QuerySnapshot> {
    val userId = Auth.currentUser()!!.uid
    val query = userGroupsQuery(groupsCollection, userId)
    return query.get()
}

第二个操作查询这些组中的相册。

fun getAlbums(): Task<Task<List<Album>>> {
    return getGroupsSnapshot().continueWith { task ->
        val documentSnapshots = TaskUtils.getResult(task)
        val albums = mutableListOf<Album>()
        val fetchAlbumTasks = documentSnapshots.documents.map { document ->
            Log.d(TAG, document["name"].toString())
            document.reference.collection("albums").get().addOnCompleteListener { queryTask ->
                albums.addAll(toObjects(Album::class.java, queryTask))
            }
        }
        return@continueWith Tasks.whenAll(fetchAlbumTasks).continueWith allTasks@ {
            return@allTasks albums as List<Album>
        }
    }
}

但是我希望此操作return键入Task<List<Album>>以保持界面干净。

要组合多个 Task,您应该使用 continueWithTask 而不是 continueWith。它接受一个 Continuation<TResult, Task<TContinuationResult> 作为参数,这基本上使返回的 Task 变平并避免嵌套。您应该将其视为 Monad 中的 mapflatMap 操作(即 List),在这种情况下,如果您将 continueWithTask 等同于 flatMap使用 List 而不是 Task 作为容器(请记住,使用 flatMap 可以将 List 的每个元素转换为新的 List,并将生成的 List)