Skip to content

Instantly share code, notes, and snippets.

@manuelvicnt
manuelvicnt / LoginUserCompiled.java
Last active March 18, 2020 11:14
LoginUser suspend fun (compiler generated code)
/* 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
/* 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
/* 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)
/* 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 {
/* 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
@Singleton
@Component(modules = [FeedCacheModule::class, DatabaseModule::class])
interface AppComponent { ... }
@Module
object FeedCacheModule {
@Provides
fun feedCache(feedDatabase: FeedDatabase): FeedCache {
return RoomFeedCache(database.feedDao())
// Bad practice
class MyViewModel() {
fun example() {
// ------------------ code smell ---------
viewModelScope.launch(Dispatchers.IO) { … }
}
}
// Inject Dispatchers as shown below!
@manuelvicnt
manuelvicnt / ShowViewModelTest.kt
Created October 9, 2019 09:00
Plaid - ShowViewModelTest solution
class ShotViewModelTest {
// This CoroutineDispatcher is injected in the ViewModel and use case
private val testCoroutineDispatcher = TestCoroutineDispatcher()
@After
fun tearDown() {
testCoroutineDispatcher.cleanupTestCoroutines()
}
@Test
@manuelvicnt
manuelvicnt / ShowViewModelTest.kt
Created October 9, 2019 08:57
Plaid - ShowViewModelTest
@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())
@manuelvicnt
manuelvicnt / ShotViewModel.kt
Created October 9, 2019 08:53
Plaid - ShotViewModel
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 { ... }
}