I am building an Android application using Jetpack compose library with Firebase. I’m rebuilding the app based on this sample builder Make it so Android.
I want to query a collection on firestore with the name "courses" (Number of documents in it is 1), but when I run the program it doesn’t show any documents and it doesn’t give me any error.
This is my firestore and rule:
And here is my code:
- CoursesServiceImpl.kt
package com.tnmd.learningenglishapp.model.service.imple
class CoursesServiceImpl @Inject
constructor(private val firestore: FirebaseFirestore, private val auth: AccountService
) : CoursesService {
override val courses: Flow<List<Courses>>
// I try to query in this
get() = firestore.collection(COURSES_COLLECTION).dataObjects()
override suspend fun getCourses(coursesId: String): Courses? =
firestore.collection(COURSES_COLLECTION).document(coursesId).get().await().toObject()
override suspend fun save(courses: Courses): String =
trace(SAVE_COURSES_TRACE){
firestore.collection(COURSES_COLLECTION).add(courses).await().id
}
override suspend fun update(courses: Courses): Unit =
trace(UPDATE_COURES_TRACE){
firestore.collection(COURSES_COLLECTION).document(courses.id).set(courses).await()
}
override suspend fun delete(coursesId: String) {
firestore.collection(COURSES_COLLECTION).document(coursesId).delete().await()
}
companion object {
private const val USER_ID_FIELD = "userId"
private const val COURSES_COLLECTION = "courses"
private const val SAVE_COURSES_TRACE = "saveCourses"
private const val UPDATE_COURES_TRACE = "updateCourses"
}
}
- CoursesViewModel.kt
package com.tnmd.learningenglishapp.screens.list_courses
@HiltViewModel
class CoursesViewModel @Inject constructor(
private val coursesService: CoursesService,
logService: LogService
) : LearningEnglishAppViewModel(logService){
val courses = coursesService.courses
}
- CoursesScreen.kt
package com.tnmd.learningenglishapp.screens.list_courses
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@Composable
@ExperimentalMaterialApi
fun CoursesScreen(
modifier: Modifier = Modifier,
viewModel: CoursesViewModel = hiltViewModel()
) {
Scaffold(
floatingActionButton = {
FloatingActionButton(
onClick = { /*viewModel.onUpdateClick(openScreen)*/ },
backgroundColor = MaterialTheme.colors.primary,
contentColor = MaterialTheme.colors.onPrimary,
modifier = modifier.padding(16.dp)
) {
Icon(Icons.Filled.Add, "Update")
}
}
) {
val courses = viewModel.courses.collectAsStateWithLifecycle(emptyList())
Column(modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()) {
Text(text = courses.value.size.toString(), color = Color.DarkGray)
LazyColumn {
items(courses.value, key = { it.id }) { coursesItem ->
CoursesItem(
courses = coursesItem
)
}
}
}
}
}
I want to query a collection on firestore with the name "courses" (Number of documents in it is 1), but when I run the program it doesn’t show any documents and it doesn’t give me any error.
2
Answers
Query takes time to load data from
firestore
as any other apis takes. So we have to do that work in a suspended function to wait for its completion. And due to this as you are not waiting it gives you empty list. You should do these following steps:Step 1. Make the
CoursesService.courses
function suspended usingsuspend
keyword in the interface as well and change the return type toList<Course>
of function to as it is not update it will give complete list ones in this case. You can do it like this:Step 2. Also make the
courses
variable of typeMutableSnapshotList<Course>
this will recompose the composable to show that updated list like this:Step 3. Also get the data in
coroutineScope
as the suspended function needs for that you need to create separate function inviewModel
or useinit
function to callCoursesService.courses
function and remember to add the new data in the list as the list isval
like this:Step 4. Now you have to wait for the query to complete and you can use
.await()
function on theResult
and then convert it intolist
like this:Make sure the document id is correct.
Set FireStore rules to allow read, write if true;
You can call all documents in a collection like this:
Check for any exception and if not, log your document in success listener.