More refactoring

pull/552/head
Don Turner 3 years ago
parent e536c396f9
commit f9dcdb4390

@ -42,7 +42,7 @@ import javax.inject.Inject
class ForYouViewModel @Inject constructor( class ForYouViewModel @Inject constructor(
syncStatusMonitor: SyncStatusMonitor, syncStatusMonitor: SyncStatusMonitor,
private val userDataRepository: UserDataRepository, private val userDataRepository: UserDataRepository,
private val getUserNewsResources: GetUserNewsResourcesUseCase, getUserNewsResources: GetUserNewsResourcesUseCase,
getFollowableTopics: GetFollowableTopicsUseCase, getFollowableTopics: GetFollowableTopicsUseCase,
) : ViewModel() { ) : ViewModel() {
@ -56,13 +56,14 @@ class ForYouViewModel @Inject constructor(
initialValue = false, initialValue = false,
) )
val feedState: StateFlow<NewsFeedUiState> = getFollowedUserNewsResources() val feedState: StateFlow<NewsFeedUiState> =
.map(NewsFeedUiState::Success) userDataRepository.getFollowedUserNewsResources(getUserNewsResources)
.stateIn( .map(NewsFeedUiState::Success)
scope = viewModelScope, .stateIn(
started = SharingStarted.WhileSubscribed(5_000), scope = viewModelScope,
initialValue = NewsFeedUiState.Loading, started = SharingStarted.WhileSubscribed(5_000),
) initialValue = NewsFeedUiState.Loading,
)
val onboardingUiState: StateFlow<OnboardingUiState> = val onboardingUiState: StateFlow<OnboardingUiState> =
combine( combine(
@ -98,50 +99,30 @@ class ForYouViewModel @Inject constructor(
userDataRepository.setShouldHideOnboarding(true) userDataRepository.setShouldHideOnboarding(true)
} }
} }
/**
* This sequence of flow transformation functions does the following:
*
* - map: maps the user data into a set of followed topic IDs or null if we should return
* an empty list
* - distinctUntilChanged: will only emit a set of followed topic IDs if it's changed. This
* avoids calling potentially expensive operations (like setting up a new flow) when nothing
* has changed.
* - flatMapLatest: getUserNewsResources returns a flow, so we have a flow inside a
* flow. flatMapLatest moves the inner flow (the one we want to return) to the outer flow
* and cancels any previous flows created by getUserNewsResources.
*/
private fun getFollowedUserNewsResources(): Flow<List<UserNewsResource>> =
userDataRepository.userData
.map { userData ->
if (userData.shouldShowEmptyFeed()) {
null
} else {
userData.followedTopics
}
}
.distinctUntilChanged()
.flatMapLatest { followedTopics ->
if (followedTopics == null) {
flowOf(emptyList())
} else {
getUserNewsResources(filterTopicIds = followedTopics)
}
}
} }
// Alternative approach (not currently being called) /**
private fun Flow<UserData>.getFollowedUserNewsResources( * Obtain a flow of user news resources whose topics match those the user is following.
*
* getUserNewsResources: The `UseCase` used to obtain the flow of user news resources.
*/
private fun UserDataRepository.getFollowedUserNewsResources(
getUserNewsResources: GetUserNewsResourcesUseCase, getUserNewsResources: GetUserNewsResourcesUseCase,
): Flow<List<UserNewsResource>> = ): Flow<List<UserNewsResource>> = userData
map { userData -> // Map the user data into a set of followed topic IDs or null if we should return an empty list.
.map { userData ->
if (userData.shouldShowEmptyFeed()) { if (userData.shouldShowEmptyFeed()) {
null null
} else { } else {
userData.followedTopics userData.followedTopics
} }
} }
// Only emit a set of followed topic IDs if it's changed. This avoids calling potentially
// expensive operations (like setting up a new flow) when nothing has changed.
.distinctUntilChanged() .distinctUntilChanged()
// getUserNewsResources returns a flow, so we have a flow inside a flow. flatMapLatest moves
// the inner flow (the one we want to return) to the outer flow and cancels any previous flows
// created by getUserNewsResources.
.flatMapLatest { followedTopics -> .flatMapLatest { followedTopics ->
if (followedTopics == null) { if (followedTopics == null) {
flowOf(emptyList()) flowOf(emptyList())

Loading…
Cancel
Save