How do you folks architect around the fact that sh...
# coroutines
u
How do you folks architect around the fact that shared flows (correctly) need scope as a parameter?. Should only classes that own their scope use sharing operators? In rx I used to do this
Copy code
class AppInForeground {
	val appInForeground: Observable<Boolean> by lazy {
		Lifecycle.wrapAsObservable()
		   .distinctUntilChanged()
		   .publish()
		   .replay(1)
	}
}
naive Flow implementation
Copy code
class AppInForeground {
	fun appInForeground(scope: CoroutineScope) {
		if (_appInForeground == null) {
			synchornized(this) {
				if(_appInForeground == null) {
					_appInForeground = Lifecycle.wrapAsFlow()
						.distinctUntilChanged()
						.shareIn(scope, SharingStarted.Lazily, 1)
				}

			}
		}
		return _appInForeground!!
	}
}
just looks stupid, however the main issue is that callers should not determine the scope, right? I think idiomatic way is this
Copy code
class AppInForeground : HasLifecycle {
	private val scope = SupervisorScope(..)

	private val _appInForeground = MutableStateFlow(false)
	val appInForeground: Flow<Boolean> get() = _appInForeground

	override fun create() {
		scope.launch {
			Lifecycle.wrapAsFlow()
				.distinctUntilChanged()
				.collect {
					_appInForeground.value = it
				}
		}
	}

	override fun destroy() {
		scope.cancel()
	}
}
Works, however its a bit less efficient, i.e. it subscribers when the AppInForeground class si instantiated, also whole lot more ceremony... Is there a way more close to the rx way? or should I just deal with it?
u
Just as a side note, double checked locking is flawed in java. Please use a different pattern for singletons or make sure
_appInForeground
is
volatile
https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
u
yea, thanks!