https://kotlinlang.org logo
#compose
Title
# compose
a

AmrJyniat

08/19/2022, 4:28 PM
I have these two pages, same design exactly except the card's content. I used compose inside activity, what do you think the best way to represent the proper content? My approach in 🧵 please correct me.
I created sealed class for UiState as the following:
Copy code
sealed class LoginUiState
data class LoginEmailUiState(val email: String = ""): LoginUiState()
data class ResetPasswordUiState(val email: String = ""): LoginUiState()
.....
Each class represent a page, then I hide\ show the proper page based on MutableStateFlow in VM like so:
Copy code
val properUiState = MutableStateFlow<LoginUiState>(LoginEmailUiState())
fun setUiState(newUiState: LoginUiState){
     uiStateSealed.value = newUiState
}
Then produce the UiState with its updated value like so:
Copy code
val uiState = properUiState.map {
        when(it){
            is LoginEmailUiState ->  combine(
                email, password, rememberLogin
            ) { em, pass, rememberLog ->
                LoginEmailUiState(em, pass, rememberLog)
            }
            is ResetPasswordUiState -> email.map {
                ResetPasswordUiState(it)
            }
            ....
        }
    }.flatMapLatest { it }.stateIn(viewModelScope, LoginUiState())
Last thing I collect the
uiState
from compose and represent the proper ui based on its value like so:
Copy code
@Composable
fun Container(loginUiState: LoginUiState){
   Card{
      when (loginUiState) {
         is LoginEmailUiState -> {
            LoginEmailContainer(loginUiState)
         }
         is ResetPasswordUiState -> {
            ResetPasswordContainer(loginUiState)
         }
         ...
      }
   }
}
This works fine, but when navigate to another page then hit back will finish the activity(make sense), so I consider to use
navigation-compose
and make each composable(
LoginEmailContainer()
,
ResetPasswordContainer()
) destination to save the backstack navigation, what do you think?
s

svenjacobs

08/20/2022, 10:04 AM
Hm, it seems you are in the process of writing your own navigation. I would rather use Jetpack Compose Navigation. Then inside your single
Activity
use a
NavHost
and define your two distinct Compose screens as routes. Then use the
NavController
to navigate between those routes.
If you want to reuse certain parts of the UI because for example the
Container
composable is identical in both screens, you could extract
Container
as a reusable composable and use the Slot API pattern to insert the different content per screen. Just a very simple example:
Copy code
@Composable
fun Container(
  modifier: Modifier = Modifier,
  content: @Composable () -> Unit,
) {
  Card(
    modifier = modifier,
    content = content,
  )

  // or alternative syntax, though more verbose
  Card(
    modifier = modifier,
  ) {
    content()
  }
}
39 Views