in my controller class, I'm passing in a `Coroutin...
# mvikotlin
t
in my controller class, I'm passing in a
CoroutineContext
in the public constructor and internally creating a new scope from it. Is that a reasonable way to handle the
CoroutineScope
for the controller and how do I need to handle the lifecycle of the scope? Details in the thread
here's my current code:
Copy code
class RecipeDetailBloc internal constructor(
    val dependencies: Dependencies, // also contains a com.arkivanov.essenty.lifecycle.Lifecycle
    private val mainContext: CoroutineContext,
    private val mainScope: CoroutineScope,
) {

    constructor(dependencies: Dependencies) : this(
        dependencies = dependencies,
        mainContext = mainDispatcher,
        mainScope = CoroutineScope(mainDispatcher)
    )

    private val recipeDetailStore =
        dependencies.instanceKeeper.getStore {
            RecipeDetailStoreFactory(
                storeFactory = dependencies.storeFactory,
                ingredientService = dependencies.ingredientService,
                ingredientRepository = dependencies.ingredientRepository,
                recipeDetailUseCase = dependencies.recipeDetailUseCase,
                mainContext = mainContext,
            ).create()
        }

    // presumably, I need to add this (haven't tested yet):
    fun destroy() {
        mainScope.cancel()
    }
    ...
is handling it via
destroy()
all that I need to do? And is it the best way to handle it in the context of controller being used in an MVIKotlin setup?
a
Yes, Lifecycle onDestroy looks like what you need. Also, perhaps you could avoid the internal constructor and just assign CoroutineScope to a private property.
t
but deriving it via
CoroutineScope(mainDispatcher)
still makes sense, right? Seems safer than having both the context and scope as constructor arguments in case the caller provides two unrelated ones
a
Yep, correct. Just pass
mainContext: CoroutineContext
and create CoroutineScope internally. This allows swapping the context with a test dispatcher in tests, yet the scope is encapsulated.
I guess, you are passing mainContext in Dependencies
t
no, I'm passing in the default value of
mainDispatcher
which is
Dispatchers.Main.immediate
. I guess I should pass it in via
dependencies
for flexibility though I don't think I'd pick a different one
a
That's still fine! The main point is the ability to replace the context in tests.
t
yeah, definitely an area I need to solidify still 🙂
ah, I think the reason I had a separate constructor was it seems Swift doesn't seem to cope with Kotlin default arguments
a
Yep, for Swift we need a separate constructor without default arguments.
t
great, I think I'm all set now. Just have some straightforward SwiftUI work (and a little MVIKotlin cleanup) between now and my next release (first using SwiftUI) 🙂
thanks for all your help again!
a
Awesome!
t
then, hopefully, it'll all be straightforward for the next couple screens (migrating to Compose and SwiftUI) then on to Decompose 🙂