Dear Compose Team. i am working on 100% compose pr...
# compose
q
Dear Compose Team. i am working on 100% compose project, we are facing issue in localization when language is changed. i observer composable screen called multiple time and button click listeners not working when locale is change, after kill the app and then its fine. might be it is due to multiple recomposition of screen when localization is change. i am sharing my code in thread please check help me out of this. #compose #compose-android
image.png
image.png,image.png,image.png
image.png
currently i am changing locale from login screen and this is a screen and when locale is change it is called multiple time
d
First of all you have suppressed the
CoroutineCreationDuringComposition
warning. That warning is telling you that every time the Composable is recomposed it is creating a new coroutine. That coroutine is not being cancelled and therefore is still collecting from the
navigationManagers.commands
Flow. You now have 1+ (N Recompositions) telling the
navController
to
navigate
to the
destination
. That will cause multiple navigations to the same
destination
.
Mainly because the
CoroutineScope
is being remembered so it’s children coroutines will not be cancelled.
I would use a
LaunchedEffect(scope) { consume commands here }
instead.
q
LaunchedEffect(scope) { consume commands here } i try this one but still the same issue. @dewildte
a
Why use a coroutine at all? If you intend to consume it in Compose, use
collectAsState
. In any case, this feels unrelated to your original issue, at least on the surface.
Plus,
configChanges="locale"
is not enough; you'd need
layoutDirection
too. And there's no point in implementing the config changed callback if it's not doing anything. Side-note: generally speaking, if your UI is fully-Compose you'd benefit from putting everything into
configChanges
, because Compose can react to colors, density, etc too.
d
@Qamar Khan the points made here are good. It's worth trying
q
@dewildte so that why i am using which works fine for locale changes.
Copy code
AppCompatDelegate.setApplicationLocales(
    LocaleListCompat.forLanguageTags(
        state.selectedLocale
    )
)
@dewildte the only issue currently i am not able to fix is NavigationManager is cancelled when activity is being recreated.
Copy code
class NavigationManager {
    var commands = Channel<NavigationCommand>(Channel.CONFLATED). // Actually this commands print cancelled,capacity=1,data=[]

    fun navigate(directions: NavigationCommand) {
        Log.e("command", commands.toString())
        val scope = CoroutineScope(Dispatchers.Default)

        scope.launch {
            try {
                commands.trySend(directions)
            } catch (e: Exception) {
                Log.e("exception", e.printStackTrace().toString())
            } finally {
                scope.cancel()
            }
        }
}when i print then logs --> cancelled,capacity=1,data=[] even we are providing this class from hilt,
Copy code
@Provides
@Singleton
fun providesNavigationManager() = NavigationManager()
d
Why is there a scope.cancel in the finally block? Why would you ever want to cancel the scope?
q
because when it send the value then i am trying to close the scope, otherwise when locale changes then scope will return null. as i showed you issue last night
d
Ah
The only other alternative I can think of might require a bit of a refactor. Instead of calling your navigation manager you instead pass a lambda all the way down to the button and call that lambda from the button
It might be a little extra work but it's a guaranteed way to get things working
q
Actually login screen is placed in a separate module and only way communication we have the NavigationManager class. if we send the value activity will observe and load the next screen. but how lamda function will works in this case. how activity will listen that something is changed
d
Oh I see.
Your NavHost is in main activity right?
q
Copy code
scope.launch {
    mainViewModel.navigationManager.commands.consumeAsFlow().collect {
        if (it.destination.isNotEmpty()) {
            navController.navigate(it.destination)
            route = it.destination
        } else {
            println(it.toString())
        }
    }
}
see we are observing from navigation Manager class inside the activity
yes brother navHost is in main activity.
navigationManager works as a bridge between Composable screen and mainActivity, when configuration changes then bridge will be break. it is cancelled, even we are using Singleton but it wont keep the same instance on recreate.
d
Ok so that's where we pass down the lambda, from the NavHost into the Authentication screen
q
@dewildte I really appreciate the time and effort you put into finding a solution for me. You are a lifesaver for me. Thanks alot brother God bless you.
d
It's my honor to help you! Thank you for being so patient and kind. I know your humble attitude is going to give you a long and happy life.
❤️ 1
Ask me anything anytime and I will try to help out.
❤️ 1