简体   繁体   English

Kotlin 协程挂起错误与 Room DataSource.Factory

[英]Kotlin coroutine suspend error with Room DataSource.Factory

Overview概述

Expected - Successfully making a Room query for a DataSource.Factory<Int, Content> in order to populate a PagedList .预期- 成功对DataSource.Factory<Int, Content>进行 Room 查询以填充PagedList This strategy is similar to the Room Coroutines implementation outlined in the Medium post by Florina Muntenescu of the Android Developer Advocate team.此策略类似于 Android 开发人员倡导团队的Florina Muntenescu在 Medium 帖子中概述的Room Coroutines实现。

Observed - The app fails to build.观察到- 应用无法构建。

Error错误

Unfortunately, there is not a more specific error to suggest the source of the issue.不幸的是,没有更具体的错误来表明问题的根源。

A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障

Implementation执行

ViewModel视图模型

  1. The ViewModel uses viewModelScope to launch getContentList() . ViewModel 使用viewModelScope来启动getContentList()
  2. getContentList() is a suspending function that calls the Repository with another suspending function getMainFeedList() . getContentList()是一个暂停的 function 调用存储库与另一个暂停 function getMainFeedList()
  3. In the Loading and Error cases a call to Room is made queryMainContentList(...) .LoadingError情况下,调用 Room 是queryMainContentList(...)
class ContentViewModel : ViewModel() {
    fun processEvent(...) {
        ...
        viewModelScope.launch {
            _feedViewState.value = FeedViewState(contentList = getContentList(...))
        }
        ...
    }

    suspend private fun getContentList(...): LiveData<PagedList<Content>> =
            switchMap(getMainFeedList(isRealtime, timeframe)) { lce ->
                when (lce) {
                    is Loading -> 
                       coroutineScope { 
                          emitSource(queryMainContentList(...)) 
                       }
                    is Lce.Content -> lce.packet.pagedList!!
                    is Error -> 
                       coroutineScope { 
                          emitSource(queryMainContentList(...)) 
                       }
                }
            }
}

Repository存储库

  1. getMainFeedList() is a suspending function that uses withContext(Dispatchers.Default) in order to get the coroutine scope. getMainFeedList()是一个暂停的 function,它使用withContext(Dispatchers.Default)来获取协程 scope。
  2. getMainFeedList() returns LiveData with the result from a Firebase Firestore collection request, contentEnCollection.get().addOnCompleteListener. getMainFeedList()从 Firebase Firestore 收集请求contentEnCollection.get().addOnCompleteListener.
  3. The Firestore result is saved to a Room DB with insertContentList() , from within the nested suspending coroutine launch {... } . Firestore 结果使用insertContentList()从嵌套的挂起协程launch {... }中保存到 Room DB。 insertContentList() works as expected using suspend . insertContentList()使用suspend按预期工作。
object ContentRepository {
    fun getMainFeedList(...) =  liveData<Lce<PagedListResult>> {
            val lce = this
            val newContentList = arrayListOf<Content?>()
            contentEnCollection.get().addOnCompleteListener {
                arrayListOf<Content?>().also { contentList ->
                    it.result!!.documents.all { document ->
                        contentList.add(document.toObject(Content::class.java))
                        true
                    }
                    newContentList.addAll(contentList)
                }
                CoroutineScope(Dispatchers.Default).launch {
                   try {
                      database.contentDao().insertContentList(newContentList)
                   } catch (e: Exception) {
                      this.cancel()
                   }
                }.invokeOnCompletion { throwable ->
                   if (throwable == null)
                      lce.emit(Lce.Content(PagedListResult(
                         pagedList = queryMainContentList(timeframe),
                         errorMessage =  "")))
                   else // Log Room error.
                }
            }.addOnFailureListener {
                // Log Firestore error here.
                lce.emit(...)
            }
        }
    }
}

suspend fun queryMainContentList(timestamp: Timestamp) =
            liveDataBuilder(database.contentDao().queryMainContentList(timestamp, MAIN))

fun liveDataBuilder(dataSource: DataSource.Factory<Int, Content>) =
        LivePagedListBuilder(dataSource,
                PagedList.Config.Builder().setEnablePlaceholders(true)
                        .setPrefetchDistance(PREFETCH_DISTANCE)
                        .setPageSize(PAGE_SIZE)
                        .build())
                .build()

Dao

insertContentList() works as expected. insertContentList()按预期工作。

@Dao
interface ContentDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertContentList(users: ArrayList<Content?>)

    @Query("SELECT * FROM content WHERE timestamp >= :timeframe AND feedType = :feedType ORDER BY timestamp DESC")
    suspend fun queryMainContentList(timeframe: Timestamp, feedType: FeedType): DataSource.Factory<Int, Content>
}

Stack Trace堆栈跟踪

The important part seems to be the following:重要的部分似乎如下:

error: Not sure how to convert a Cursor to this method's return type (androidx.paging.DataSource.Factory).错误:不确定如何将 Cursor 转换为此方法的返回类型 (androidx.paging.DataSource.Factory)。

Here is the full log:这是完整的日志:

21:50:30: Executing task 'assembleAndroidTest'... 21:50:30:执行任务“assembleAndroidTest”...

Executing tasks: [assembleAndroidTest] in project /Users/adamhurwitz/Coinverse/android执行任务:项目/Users/adamhurwitz/Coinverse/android中的[assembleAndroidTest]

Configure project:app WARNING: The following project options are deprecated and have been removed: android.databinding.enableV2 Databinding v1 is removed.配置项目:应用程序警告:以下项目选项已弃用并已删除:android.databinding.enableV2 数据绑定 v1 已删除。

WARNING: The option setting 'android.enableR8.fullMode=true' is experimental and unsupported.警告:选项设置“android.enableR8.fullMode=true”是实验性的,不受支持。 The current default is 'false'.当前默认值为“假”。

WARNING: API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'.警告:API 'variant.getAssemble()' 已过时并已替换为 'variant.getAssembleProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variant.getAssemble(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variant.getAssemble() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variantOutput.getProcessResources()' is obsolete and has been replaced with 'variantOutput.getProcessResourcesProvider()'.警告:API 'variantOutput.getProcessResources()' 已过时并已替换为 'variantOutput.getProcessResourcesProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variantOutput.getProcessResources(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variantOutput.getProcessResources() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variantOutput.getProcessManifest()' is obsolete and has been replaced with 'variantOutput.getProcessManifestProvider()'.警告:API 'variantOutput.getProcessManifest()' 已过时并已替换为 'variantOutput.getProcessManifestProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variantOutput.getProcessManifest(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variantOutput.getProcessManifest() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variant.getMergeResources()' is obsolete and has been replaced with 'variant.getMergeResourcesProvider()'.警告:API 'variant.getMergeResources()' 已过时并已替换为 'variant.getMergeResourcesProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variant.getMergeResources(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variant.getMergeResources() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variant.getMergeAssets()' is obsolete and has been replaced with 'variant.getMergeAssetsProvider()'.警告:API 'variant.getMergeAssets()' 已过时并已替换为 'variant.getMergeAssetsProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variant.getMergeAssets(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variant.getMergeAssets() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variant.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.警告:API 'variant.getPackageApplication()' 已过时并已替换为 'variant.getPackageApplicationProvider()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variant.getPackageApplication(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variant.getPackageApplication() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。 WARNING: API 'variant.getExternalNativeBuildTasks()' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders()'.警告:API 'variant.getExternalNativeBuildTasks()' 已过时并已替换为 'variant.getExternalNativeBuildProviders()'。 It will be removed at the end of 2019. For more information, see https://d.android.com/r/tools/task-configuration-avoidance .它将在 2019 年底被删除。有关更多信息,请参阅https://d.android.com/r/tools/task-configuration-avoidance To determine what is calling variant.getExternalNativeBuildTasks(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.要确定调用 variant.getExternalNativeBuildTasks() 的内容,请在命令行上使用 -Pandroid.debug.obsoleteApi=true 以显示更多信息。

Task:app:preBuild UP-TO-DATE Task:app:preDebugBuild UP-TO-DATE Task:app:mergeDebugShaders UP-TO-DATE Task:app:compileDebugShaders UP-TO-DATE Task:app:generateDebugAssets UP-TO-DATE Task:app:processDebugGoogleServices UP-TO-DATE Task:app:checkDebugManifest UP-TO-DATE Task:app:createDebugCompatibleScreenManifests UP-TO-DATE Task:app:mainApkListPersistenceDebug UP-TO-DATE Task:app:generateDebugBuildConfig UP-TO-DATE Task:app:compileDebugAidl NO-SOURCE Task:app:compileDebugRenderscript NO-SOURCE Task:app:mergeDebugAssets UP-TO-DATE Task:app:processDebugManifest UP-TO-DATE Task:app:fabricGenerateResourcesDebug Task:app:writeDebugApplicationId UP-TO-DATE Task:app:generateSafeArgsDebug UP-TO-DATE Task:app:prepareLintJar UP-TO-DATE Task:app:prepareLintJarForPublish UP-TO-DATE Task:app:generateDebugSources Task:app:dataBindingExportBuildInfoDebug UP-TO-DATE Task:app:dataBindingMergeDependencyArtifactsDebug UP-TO-DATE Task:app:generateDebugResValues UP-TO-DATE Task:app:dataBindingMergeGenClasses任务:app:preBuild 最新任务:app:preDebugBuild 最新任务:app:mergeDebugShaders 最新任务:app:compileDebugShaders 最新任务:app:generateDebugAssets 最新Task:app:processDebugGoogleServices 最新 Task:app:checkDebugManifest 最新 Task:app:createDebugCompatibleScreenManifests 最新 Task:app:mainApkListPersistenceDebug 最新 Task:app:generateDebugBuildConfig 最新Task:app:compileDebugAidl NO-SOURCE Task:app:compileDebugRenderscript NO-SOURCE Task:app:mergeDebugAssets UP-TO-DATE Task:app:processDebugManifest UP-TO-DATE Task:app:fabricGenerateResourcesDebug Task:app:writeDebugApplicationId UP-TO-日期任务:app:generateSafeArgsDebug 最新任务:app:prepareLintJar 最新任务:app:prepareLintJarForPublish 最新任务:app:generateDebugSources 任务:app:dataBindingExportBuildInfoDebug 最新任务:app: dataBindingMergeDependencyArtifactsDebug 最新任务:app:generateDebugResValues 最新任务:app:dataBindingMergeGenClasses Debug UP-TO-DATE Task:app:generateDebugResources UP-TO-DATE Task:app:dataBindingExportFeaturePackageIdsDebug UP-TO-DATE Task:app:preDebugAndroidTestBuild SKIPPED Task:app:compileDebugAndroidTestAidl NO-SOURCE Task:app:processDebugAndroidTestManifest UP-TO-DATE Task:app:compileDebugAndroidTestRenderscript NO-SOURCE Task:app:generateDebugAndroidTestBuildConfig UP-TO-DATE Task:app:mainApkListPersistenceDebugAndroidTest UP-TO-DATE Task:app:generateDebugAndroidTestResValues UP-TO-DATE Task:app:generateDebugAndroidTestResources UP-TO-DATE Task:app:mergeDebugAndroidTestResources UP-TO-DATE Task:app:processDebugAndroidTestResources UP-TO-DATE Task:app:mergeDebugAndroidTestShaders UP-TO-DATE Task:app:compileDebugAndroidTestShaders UP-TO-DATE Task:app:generateDebugAndroidTestAssets UP-TO-DATE Task:app:mergeDebugAndroidTestAssets UP-TO-DATE Task:app:processDebugAndroidTestJavaRes NO-SOURCE Task:app:mergeDebugAndroidTestJniLibFolders UP-TO-DATE Task:app:mergeDebugAndroidTestNativeLibs UP-TO-DATE T调试最新任务:app:generateDebugResources 最新任务:app:dataBindingExportFeaturePackageIdsDebug 最新任务:app:preDebugAndroidTestBuild 跳过任务:app:compileDebugAndroidTestAidl 无源任务:app:processDebugAndroidTestManifest 最新任务:app:compileDebugAndroidTestRenderscript 无源任务:app:generateDebugAndroidTestBuildConfig 最新任务:app:mainApkListPersistenceDebugAndroidTest 最新任务:app:generateDebugAndroidTestResValues 最新任务:app:generateDebugAndroidTestResources 最新任务: app:mergeDebugAndroidTestResources 最新任务:app:processDebugAndroidTestResources 最新任务:app:mergeDebugAndroidTestShaders 最新任务:app:compileDebugAndroidTestShaders 最新任务:app:generateDebugAndroidTestAssets 最新任务: app:mergeDebugAndroidTestAssets 最新任务:app:processDebugAndroidTestJavaRes 无源任务:app:mergeDebugAndroidTestJniLibFolders 最新任务:app:mergeDebugAndroidTestNativeLibs 最新 T ask:app:checkDebugAndroidTestDuplicateClasses UP-TO-DATE Task:app:validateSigningDebugAndroidTest UP-TO-DATE Task:app:signingConfigWriterDebugAndroidTest UP-TO-DATE /Users/adamhurwitz/Coinverse/android/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:1002: warn: multiple substitutions specified in non-positional format; ask:app:checkDebugAndroidTestDuplicateClasses UP-TO-DATE Task:app:validateSigningDebugAndroidTest UP-TO-DATE Task:app:signingConfigWriterDebugAndroidTest UP-TO-DATE /Users/adamhurwitz/Coinverse/android/app/build/intermediates/incremental/mergeDebugResources/merged .dir/values/values.xml:1002:警告:以非位置格式指定多个替换; did you mean to add the formatted="false" attribute?.您是要添加 formatted="false" 属性吗? /Users/adamhurwitz/Coinverse/android/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:1031: warn: multiple substitutions specified in non-positional format; /Users/adamhurwitz/Coinverse/android/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:1031:警告:以非位置格式指定多个替换; did you mean to add the formatted="false" attribute?.您是要添加 formatted="false" 属性吗?

Task:app:mergeDebugResources Task:app:dataBindingGenBaseClassesDebug UP-TO-DATE Task:app:processDebugResources Task:app:kaptGenerateStubsDebugKotlin UP-TO-DATE Task:app:mergeDebugResources Task:app:dataBindingGenBaseClassesDebug UP-TO-DATE Task:app:processDebugResources Task:app:kaptGenerateStubsDebugKotlin UP-TO-DATE

Task:app:kaptDebugKotlin FAILED ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1/Users/adamhurwitz/Coinverse/android/app/build/tmp/kapt3/stubs/debug/app/coinverse/content/room/ContentDao.java:17: error: Not sure how to convert a Cursor to this method's return type (androidx.paging.DataSource.Factory). Task:app:kaptDebugKotlin FAILED ANTLR Tool version 4.5.3 used for code generation doesn't match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compiler doesn't match the current runtime version 4.7.1ANTLR Tool version 4.5.3用于代码生成与当前运行时版本不匹配 4.7.1ANTLR 运行时版本 4.5.3 用于解析器编译与当前运行时版本不匹配 4.7.1/Users/adamhurwitz/Coinverse/android/app/build/tmp/kapt3/ stubs/debug/app/coinverse/content/room/ContentDao.java:17:错误:不确定如何将 Cursor 转换为此方法的返回类型 (androidx.paging.DataSource.Factory)。 public abstract java.lang.Object queryLabeledContentList(@org.jetbrains.annotations.NotNull() Note: 1 Wrote GeneratedAppGlideModule with: [][WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.lifecycle.LifecycleProcessor (NON_INCREMENTAL). ^ FAILURE: Build failed with an exception. public abstract java.lang.Object queryLabeledContentList(@org.jetbrains.annotations.NotNull() 注意: 1使用:[][WARN] 编写 GeneratedAppGlideModule 与:[][WARN] 增量不是注释处理请求,但 android.x 支持已禁用增量生命周期.LifecycleProcessor (NON_INCREMENTAL)。^ FAILURE:构建失败并出现异常。

  • What went wrong: Execution failed for task ':app:kaptDebugKotlin'.出了什么问题:任务':app:kaptDebugKotlin'执行失败。 A failure occurred while executing > org.jetbrains.kotlin.gradle.internal.KaptExecution java.lang.reflect.InvocationTargetException (no error message)执行 > org.jetbrains.kotlin.gradle.internal.KaptExecution java.lang.reflect.InvocationTargetException 时发生故障(无错误消息)

  • Try: Run with --stacktrace option to get the stack trace.尝试:使用 --stacktrace 选项运行以获取堆栈跟踪。 Run with --info or --debug option to get more log output.使用 --info 或 --debug 选项运行以获得更多日志 output。 Run with --scan to get full insights.运行 --scan 以获得完整的见解。

  • Get more help at https://help.gradle.orghttps://help.gradle.org获得更多帮助

BUILD FAILED in 9s 38 actionable tasks: 4 executed, 34 up-to-date 21:50:40: Task execution finished 'assembleAndroidTest'. 9 秒内构建失败 38 个可操作任务:4 个已执行,34 个最新 21:50:40:任务执行完成“assembleAndroidTest”。

PagedList分页列表

A PagedList handles loading data on the background thread by default.默认情况下, PagedList处理在后台线程上加载数据。

If you use LivePagedListBuilder to get a LiveData, it will initialize PagedLists on a background thread for you.如果您使用 LivePagedListBuilder 获取 LiveData,它将在后台线程上为您初始化 PagedLists。

  • It is not needed to mark a Dao method as suspend that produces a DataSource.Factory .不需要将 Dao 方法标记为产生DataSource.Factorysuspend The return type is used by the annotation processor to know what kind of code to generate, just like the suspend modifier is.注释处理器使用返回类型来知道要生成什么样的代码,就像suspend修饰符一样。

  • A DataSource when used together with a LiveData<PagedList> will execute queries off the main thread to safely call non-suspendable database and blocking network calls.当与LiveData<PagedList>一起使用时, DataSource将在主线程之外执行查询,以安全地调用非暂停数据库和阻塞网络调用。

LiveData实时数据

  • There is no need to mark a DAO method that returns LiveData to be suspendable since the ArchTaskExecutor makes sure that queries are run off the UI thread, and results are delivered on the UI thread.无需将返回LiveData的 DAO 方法标记为可挂起,因为ArchTaskExecutor确保查询在 UI 线程之外运行,并且结果在 UI 线程上传递。

  • To construct LiveData that calls suspendable methods, you can use the liveData {} builder extension from lifecycle-livedata-ktx extensions artifact.要构造调用可暂停方法的LiveData ,您可以使用来自lifecycle-livedata-ktx扩展工件的liveData {}构建器扩展。

  • There is also a LiveData-builder that constructs a LiveData<PagedList> directly from your DataSource.Factory , check out the paging-runtime-ktx artifact.还有一个 LiveData-builder 直接从您的DataSource.Factory构造一个LiveData<PagedList> ,请查看paging-runtime-ktx工件。

  • Also, I would not recommend returning MutableLiveData like that.另外,我不建议这样返回MutableLiveData Mutable livedata is usually mutated in private, and returned as a non-mutable LiveData object.可变的 livedata 通常是私有的,并作为非可变的LiveData object 返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有多视图 RecyclerView 的 Room DataSource.Factory - Room DataSource.Factory with multiple view RecyclerView Android 分页库 - Map 房间 DataSource.Factory&lt;*, DatabaseModel&gt; 到 DataSource.Factory&lt;*, PresenterModel&gt; - Android Paging Library - Map Room DataSource.Factory<*, DatabaseModel> to DataSource.Factory<*, PresenterModel> 房间本地单元测试 - 从 DataSource.Factory 查询 PagedList - Room Local Unit Test - Query PagedList from DataSource.Factory Android Room 在使用 DataSource.Factory 时如何按文本搜索? - Android Room how to search by text when using DataSource.Factory? Android体系结构组件分页DataSource.Factory错误 - Android architecture components paging DataSource.Factory error 将 jetbrain 插件 5.31 升级到 6.0 时,在片段 kotlin 房间协程上使用挂起时出错 - Error with use of suspend on fragment kotlin room coroutine when upgrade jetbrain plugin 5.31 to 6.0 没有挂起函数的 Kotlin 协程 - Kotlin coroutine with no suspend functions 如何从 DataSource.Factory 获取数据 - How to get data from DataSource.Factory Kotlin 协程中挂起函数的问题 - Problem with suspend function in Kotlin coroutine 暂停kotlin coroutine异步子功能 - Suspend kotlin coroutine async subfunction
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM