Skip to content

Instantly share code, notes, and snippets.

class UserRepository(
private val userEventsDataSource: FirestoreUserEventDataSource
) {
// New collectors will register as a new callback in Firestore.
// As this function depends on a `userId`, the flow cannot be
// reused by calling shareIn or stateIn in this function.
// That will cause a new Shared/StateFlow to be created
// every time the function is called.
fun getUserEvents(userId: String): Flow<UserEventsResult> =
userLocalDataSource.getObservableUserEvents(userId)
class LocationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create a new coroutine since repeatOnLifecycle is a suspend function
lifecycleScope.launch {
// The block passed to repeatOnLifecycle is executed when the lifecycle
// is at least STARTED and is cancelled when the lifecycle is STOPPED.
// It automatically restarts the block when the lifecycle is STARTED again.
repeatOnLifecycle(Lifecycle.State.STARTED) {
class LocationFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// ...
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
locationProvider.locationFlow().collect {
// New location! Update the map
}
}
}
@manuelvicnt
manuelvicnt / ProvideViewModels.kt
Last active June 7, 2024 22:31
Scope ViewModels to Composables
// PLEASE, READ
//
// This is a way to scope ViewModels to the Composition.
// However, this doesn't survive configuration changes or procress death on its own.
// You can handle all config changes in compose by making the activity handle those in the Manifest file
// e.g. android:configChanges="colorMode|density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode">
//
// This is just an exploration to see what's possible in Compose. We don't encourage developers to copy-paste
// this code if they don't fully understand the implications of it and if this actually solves the use case to solve.
class MyRepository(private val externalScope: CoroutineScope) { /* ... */ }
class MyApplication : Application() {
// Application-scoped types that any class in the app could access
// using the applicationContext.
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
val myRepository = MyRepository(applicationScope)
}
class ApplicationDiContainer {
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
val myRepository = MyRepository(applicationScope)
}
class MyApplication : Application() {
val applicationDiContainer = ApplicationDiContainer()
}
class ApplicationDiContainer {
// Scoped type. Same instance is always returned
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
// Unscoped type. Always returns a different instance
fun getMyRepository(): MyRepository {
return MyRepository(applicationScope)
}
}
@HiltAndroidApp
class MyApplication : Application()
@Singleton // Scopes this type to the SingletonComponent
class MyRepository @Inject constructor(
private val externalScope: CoroutineScope
) {
/* ... */
}
@InstallIn(SingletonComponent::class)
@Module
object CoroutinesScopesModule {
@Singleton // Provide always the same instance
@Provides
fun providesCoroutineScope(): CoroutineScope {
// Run this code when providing an instance of CoroutineScope
return CoroutineScope(SupervisorJob() + Dispatchers.Default)
}