https://kotlinlang.org logo
#decompose
Title
# decompose
j

Jan

10/09/2023, 7:30 AM
Hi @Arkadii Ivanov, all good things are three so here is another question. More in thread:
I have a RootComponent with a SlotNavigation
Within that RootComponent I have a flow to determine the state of the app and I start listining to it within the init of RootComponent
An initial slot is activated und slotNavigation persistent is set to true
After orientation change occured the flow is somehow broken due I do not get events anymore
Its working again if I explicit dismiss the last active config in my slot navigation on destroy
I have the feeling that the slotChild does somehow not recognize that a new component was created due orientation change and probably leaks
My RootComponent looks something like this:
Copy code
class RootComponent(
    private val componentContext: ComponentContext,
    private val getRootState: GetRootStateUsecase
) : ComponentContext by componentContext, KoinComponent {
private val slotNavigation = SlotNavigation<SlotConfig>()

    private val _slot = childSlot(
        source = slotNavigation,
        initialConfiguration = { SlotConfig.Home }
    ) { config, childComponentContext ->
        when (config) {
            else ->
                HomeComponent(
                    componentContext = childComponentContext,
                    componentViewModel = childComponentContext.instanceKeeper.getOrCreate {
                        getKoin().get()
                    },
                    headerViewModel = childComponentContext.instanceKeeper.getOrCreate {
                        getKoin().get()
                    }
                )
        }
    }

    val slot: Value<ChildSlot<*, *>> = _slot

    private val componentScope = coroutineScope(Dispatchers.Main + SupervisorJob())

    init {
        lifecycle.doOnDestroy {
            //slotNavigation.dismiss()
        }

        componentScope.launch {
            getRootState().collect { config ->
                println("RootComponent received new state config: $config")

            }
        }
    }
}
is that correct that I have to dismiss it manually even though I set persitent = true on my slotNavigation?
a

Arkadii Ivanov

10/09/2023, 8:54 AM
The "persistent" flag means that the slot will stay active on configuration change. So you usually don't need to manually close the slot on destroy.
j

Jan

10/09/2023, 8:55 AM
Yes, but unfortunately if I don't do so my flow breaks
a

Arkadii Ivanov

10/09/2023, 8:56 AM
Can you show more code? What is getRootState?
j

Jan

10/09/2023, 8:57 AM
Its just a UseCase wich links to a repository and returns a flow:
Copy code
class GetRootStateUsecase(
    private val rootStateRepository: RootStateRepository
) {
    suspend operator fun invoke(): Flow<RootComponent.SlotConfig> = rootStateRepository.getState()
}
Copy code
interface RootStateRepository {
    suspend fun getState(): Flow<RootComponent.SlotConfig>
}

class RootStateRepositoryImpl(
    private val ioDispatcher: CoroutineDispatcher,
    private val venueRepository: VenueRepository,
    private val userRepository: UserRepository
) : RootStateRepository {

    override suspend fun getState(): Flow<RootComponent.SlotConfig> = flow {
        val selectedVenueFlow = venueRepository.getSelectedVenue()
        val selectedUserFlow = userRepository.getSelectedUser()
        selectedVenueFlow.combine(selectedUserFlow) { selectedVenue, selectedUser ->
            State(
                venue = selectedVenue,
                user = selectedUser
            )
        }.distinctUntilChanged().collect {
            if (it.venue == null) {
                emit(RootComponent.SlotConfig.Inventory)
            } else if (it.user == null) {
                emit(RootComponent.SlotConfig.Login)
            } else {
                emit(RootComponent.SlotConfig.Dashboard)
            }
        }
    }.flowOn(ioDispatcher)
}

private data class State(
    val venue: Venue?,
    val user: User?
)
If I use a stack-navigation instead of slot-navigation it seems to work correctly
a

Arkadii Ivanov

10/09/2023, 9:00 AM
Thanks. Based on the code I can't say what's wrong. I recommend to create a minimal reproducer so I could check.
j

Jan

10/09/2023, 9:01 AM
ok, I will. It feels like that slot within the composable is somehow not in sync anymore
a

Arkadii Ivanov

10/09/2023, 9:03 AM
I suspect you have a leak in either componentViewModel or headerViewModel
j

Jan

10/09/2023, 9:03 AM
probably but I thing I checked that
a

Arkadii Ivanov

10/09/2023, 9:05 AM
But I would rather find the leak
j

Jan

10/09/2023, 9:06 AM
hehe
me too 😉
ok, I think I found my leak
🎉 1
sorry for bothering you
a

Arkadii Ivanov

10/09/2023, 9:46 AM
Yay!
j

Jan

10/09/2023, 10:59 AM
ok, it was not even a leak!
I stopped started/stopped koin during orientation change (oncreate/ondestroy in activity) and therefore my viewmodels broke
a

Arkadii Ivanov

10/09/2023, 11:00 AM
Thanks for sharing! Koin was my second suspect. 😀