Trying to get compose + hilt + compose navigation ...
# compose
c
Trying to get compose + hilt + compose navigation working for a single activity app that has your typical logged in and logged out screens. Currently I see that my HomeScreen gets loaded twice? Am I doing something wrong? Code in thread.
Copy code
2021-07-23 16:00:13.146 4110-4110/com.rollertoaster.app E/mylog: logged in
2021-07-23 16:00:13.218 4110-4110/com.rollertoaster.app E/mylog: logged in
Copy code
@Composable
fun HomeScreen(navController: NavController, viewModel: HomeScreenViewModel = hiltViewModel()) {
    if (viewModel.isLoggedIn()) {
        HomePageContent(navController = navController)
    } else {
        // go to sign up page
    }
}
VM
Copy code
@HiltViewModel
class HomeScreenViewModel
@Inject
constructor(
    private val savedStateHandle: SavedStateHandle,
) : ViewModel() {
    fun isLoggedIn(): Boolean {
        Log.e("mylog", "logged in")
        return true
    }
}
a
Home screen might be recomposing and since your tracking the log every time it recomposes it prints the log ?
c
I don't get how you're supposed to set something like logged in/out with compose and compose navigation then.
a
If your setting something that needs to be a one off then either SideEffect or LaunchedEffect might be the right fit. If your getting something then exposing a state flow and observing it might a way to do it
So in my side project this sorta works like this I have the state exposed like this and then in my composable I used it like this. Please not that this is inside of KMM project so it might be a bit different that normal
In the above example checkAuthentication also sets the authentication in case nothing is present
c
So my isLoggedIn() method should really be me reading state so it doesn't get called again until it changes?
Updated my code to this so that I basically use state instead of calling a method
Copy code
if (viewModel.isLoggedIn) {
        Log.e("mylog", "log in")
        HomePageContent(navController = navController)
    } else {
        Log.e("mylog", "log out")
        // log out
    }
and my VM
Copy code
@HiltViewModel
class HomeScreenViewModel
@Inject
constructor(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    var isLoggedIn by mutableStateOf(true)
}
and I still get the same thing... which is curious to me
Copy code
2021-07-23 17:40:56.065 8639-8639/com.rollertoaster.app E/mylog: log in
2021-07-23 17:40:56.146 8639-8639/com.rollertoaster.app E/mylog: log in
a
Hmm curious ! I am not sure why your composable is recomposing
i
You should absolutely expect every composable to go through multiple recompositions (in particular, you'll get recomposed on every frame of any animation - such as the Crossfade you get with Navigation in alpha05
c
Interesting. Alright. So I guess I shouldn't look too far into the "duplicative" logs. @ Ian in terms of actual implementation though, would you say I'm on the right path of how I would make the decision for what to do when a user is logged out on a particular screen? I have the login complementary code to this written and it doesn't navigate as I expect, and I feel like something just isn't clicking for me here.
a
You could potentially make the logged in state boolean a StateFlow object and the collect it as a state inside of your composable. That ways whenever the state changes, the composable will be recomposed and you can then express your UI in terms of the different state. I think the current problem is that you aren't constantly observing the state variable in your view model so whatever the state is when the composable was last recomposed is what is known to the composable and any changes in state aren't propagated
The link I provided to you shows you an example of how to use StateFlows to achieve what I mentioned above
c
I'm observing the state already via snapshot state
a
ohh ok :) My bad