Created
October 25, 2019 18:56
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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