Skip to content

Instantly share code, notes, and snippets.

@AniketSK
Created October 25, 2019 18:56
Show Gist options
  • Save AniketSK/403459661f13bbc6ff13a6802b73ce0d to your computer and use it in GitHub Desktop.
Save AniketSK/403459661f13bbc6ff13a6802b73ce0d to your computer and use it in GitHub Desktop.
A way to combine data from two collections when you can't use a collectionGroup because you're not supposed to be able to access all the data from one of the lists!
package com.aniketkadam.dogether.goals
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import com.aniketkadam.dogether.auth.FIREBASE_USER_ID
import com.aniketkadam.dogether.di.data.PRIVATE_GOALS_LOCATION_NAME
import com.aniketkadam.dogether.di.data.PUBLIC_GOALS_LOCATION_NAME
import com.aniketkadam.dogether.goals.data.GoalsListLiveData
import com.google.firebase.firestore.CollectionReference
import com.google.firebase.firestore.QueryDocumentSnapshot
import javax.inject.Inject
import javax.inject.Named
class GoalListRepository @Inject constructor(
@Named(PUBLIC_GOALS_LOCATION_NAME) val publicGoalsLocation: CollectionReference,
@Named(PRIVATE_GOALS_LOCATION_NAME) val privateGoalsLocation: CollectionReference,
@Named(FIREBASE_USER_ID) private val userId: String?
) {
private val queryConversion: (QueryDocumentSnapshot) -> GoalWithMetadata =
{ snapshot -> GoalWithMetadata(snapshot.id, snapshot.toObject(Goal::class.java)) }
fun getOwnGoals(): LiveData<List<GoalWithMetadata>> = CombinedLocations(
GoalsListLiveData(privateGoalsLocation, queryConversion),
GoalsListLiveData(publicGoalsLocation, queryConversion) {it.whereEqualTo(UID_PARAM, userId)}
)
fun getAllGoals(): LiveData<List<GoalWithMetadata>> = CombinedLocations(
GoalsListLiveData(privateGoalsLocation, queryConversion),
GoalsListLiveData(publicGoalsLocation, queryConversion)
)
}
/**
* Combines several sources of goals list live data into a single one.
* However, it can't deal with infinite lists and paging will need to be handled separately
*/
private class CombinedLocations(vararg goalsListLiveData: GoalsListLiveData<GoalWithMetadata>) : MediatorLiveData<List<GoalWithMetadata>>() {
private var privateSource : MutableMap<Int, List<GoalWithMetadata>> = mutableMapOf()
private fun refresh() {
postValue(privateSource.values.reduce { acc, list -> acc.plus(list) })
}
init {
goalsListLiveData.forEachIndexed { index, currentData ->
addSource(currentData) {
privateSource.put(index, it)
refresh()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment