Overview
Expected - Successfully making a Room query for a DataSource.Factory<Int, Content> in order to populate a PagedList. This strategy is similar to the Room ???? Coroutines implementation outlined in the Medium post by Florina Muntenescu of the Android Developer Advocate team.
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
Implementation
ViewModel
- The ViewModel uses
viewModelScopeto launchgetContentList(). getContentList()is a suspending function that calls the Repository with another suspending functiongetMainFeedList().- In the
LoadingandErrorcases a call to Room is madequeryMainContentList(...).
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
getMainFeedList()is a suspending function that useswithContext(Dispatchers.Default)in order to get the coroutine scope.getMainFeedList()returns LiveData with the result from a Firebase Firestore collection request,contentEnCollection.get().addOnCompleteListener.- The Firestore result is saved to a Room DB with
insertContentList(), from within the nested suspending coroutinelaunch { ... }.insertContentList()works as expected usingsuspend.
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.
@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).
Here is the full log:
21:50:30: Executing task 'assembleAndroidTest'...
Executing tasks: [assembleAndroidTest] in project /Users/adamhurwitz/Coinverse/android
Configure project :app WARNING: The following project options are deprecated and have been removed: android.databinding.enableV2 Databinding v1 is removed.
WARNING: The option setting 'android.enableR8.fullMode=true' is experimental and unsupported. The current default is 'false'.
WARNING: API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variantOutput.getProcessResources()' is obsolete and has been replaced with 'variantOutput.getProcessResourcesProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variantOutput.getProcessManifest()' is obsolete and has been replaced with 'variantOutput.getProcessManifestProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variant.getMergeResources()' is obsolete and has been replaced with 'variant.getMergeResourcesProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variant.getMergeAssets()' is obsolete and has been replaced with 'variant.getMergeAssetsProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variant.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'. It will be removed at the end of 2019. For more information, see 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. WARNING: API 'variant.getExternalNativeBuildTasks()' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders()'. It will be removed at the end of 2019. For more information, see 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.
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:dataBindingMergeGenClassesDebug 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 Task :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; did you mean to add the formatted="false" attribute?. /Users/adamhurwitz/Coinverse/android/app/build/intermediates/incremental/mergeDebugResources/merged.dir/values/values.xml:1031: warn: multiple substitutions specified in non-positional format; did you mean to add the formatted="false" attribute?.
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). 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.
What went wrong: Execution failed for task ':app:kaptDebugKotlin'. A failure occurred while executing > org.jetbrains.kotlin.gradle.internal.KaptExecution java.lang.reflect.InvocationTargetException (no error message)
Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Get more help at https://help.gradle.org
BUILD FAILED in 9s 38 actionable tasks: 4 executed, 34 up-to-date 21:50:40: Task execution finished 'assembleAndroidTest'.
A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecutionwhich only occurs upon implementing the above. - Adam Hurwitz