This file contains hidden or 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
/* Copyright 2019 Google LLC. | |
SPDX-License-Identifier: Apache-2.0 */ | |
fun loginUser(userId: String?, password: String?, completion: Continuation<Any?>) { | |
... | |
val continuation = completion as? LoginUserStateMachine ?: LoginUserStateMachine(completion) | |
when(continuation.label) { | |
0 -> { | |
// Checks for failures |
This file contains hidden or 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
/* Copyright 2019 Google LLC. | |
SPDX-License-Identifier: Apache-2.0 */ | |
class FirebaseAuthStateUserDataSource(...) : AuthStateUserDataSource { | |
private val channel = ConflatedBroadcastChannel<Result<AuthenticatedUserInfo>>() | |
private val listener: ((FirebaseAuth) -> Unit) = { auth -> | |
// Data processing logic | |
// Send the current user for observers |
This file contains hidden or 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
/* Copyright 2019 Google LLC. | |
SPDX-License-Identifier: Apache-2.0 */ | |
override fun getObservableUserEvent(userId: String, eventId: SessionId): Flow<UserEventResult> { | |
// 1) Create Flow with channelFlow | |
return channelFlow<UserEventResult> { | |
val eventDocument = firestore.collection(USERS_COLLECTION) | |
.document(userId) | |
.collection(EVENTS_COLLECTION) |
This file contains hidden or 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
/* Copyright 2019 Google LLC. | |
SPDX-License-Identifier: Apache-2.0 */ | |
// Simplified version of the real code | |
class SessionDetailViewModel( | |
private val loadUserSessionUseCase: LoadUserSessionUseCase, | |
... | |
): ViewModel() { | |
private fun listenForUserSessionChanges(sessionId: SessionId) { | |
viewModelScope.launch { |
This file contains hidden or 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
/* Copyright 2019 Google LLC. | |
SPDX-License-Identifier: Apache-2.0 */ | |
class DefaultSessionAndUserEventRepository( | |
private val userEventDataSource: UserEventDataSource, | |
private val sessionRepository: SessionRepository | |
) : SessionAndUserEventRepository { | |
override fun getObservableUserEvent( | |
userId: String?, | |
eventId: SessionId |
This file contains hidden or 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
@Singleton | |
@Component(modules = [FeedCacheModule::class, DatabaseModule::class]) | |
interface AppComponent { ... } | |
@Module | |
object FeedCacheModule { | |
@Provides | |
fun feedCache(feedDatabase: FeedDatabase): FeedCache { | |
return RoomFeedCache(database.feedDao()) |
This file contains hidden or 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
// Bad practice | |
class MyViewModel() { | |
fun example() { | |
// ------------------ code smell --------- | |
viewModelScope.launch(Dispatchers.IO) { … } | |
} | |
} | |
// Inject Dispatchers as shown below! |
This file contains hidden or 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
class ShotViewModelTest { | |
// This CoroutineDispatcher is injected in the ViewModel and use case | |
private val testCoroutineDispatcher = TestCoroutineDispatcher() | |
@After | |
fun tearDown() { | |
testCoroutineDispatcher.cleanupTestCoroutines() | |
} | |
@Test |
This file contains hidden or 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
@Test | |
fun loadShot_emitsTwoUiModels() { | |
// When the ViewModel has started | |
val viewModel = ... // Creates viewModel | |
// Then the fast result has been emitted | |
val fastResult = viewModel.shotUiModel.getOrAwaitValue() | |
// THIS FAILS!!! The slow result has already been emitted because the coroutine | |
// was executed immediately and shotUiModel LiveData contains the slow result | |
assertTrue(fastResult.formattedDescription.isEmpty()) |
This file contains hidden or 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
class ShotViewModel(...) { | |
init { | |
val result = shotsRepository.getShot(shotId) | |
if (result is Result.Success) { | |
// FIRST UI EMISSION with an incomplete UI Model | |
_shotUiModel.value = result.data.toShotUiModel() | |
processUiModel(result.data) | |
} else { ... } | |
} |