MainActivity
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject
lateinit var connectivityManager: ConnectivityManager
@Inject
lateinit var settingsDataStore: SettingsDataStore
override fun onStart() {
super.onStart()
connectivityManager.registerConnectionObserver(this)
}
override fun onDestroy() {
super.onDestroy()
connectivityManager.unregisterConnectionObserver(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = Screen.Login.route) {
composable(
route = Screen.Login.route
) { navBackStackEntry ->
val factory = HiltViewModelFactory(LocalContext.current, navBackStackEntry)
val viewModel: LoginViewModel = viewModel(key = "LoginViewModel", factory = factory)
LoginScreen(
isNetworkAvailable = connectivityManager.isNetworkAvailable.value,
onNavigateToHomeScreen = navController::navigate,
viewModel = viewModel
)
}
composable(
route = Screen.Home.route
) { navBackStackEntry ->
val factory = HiltViewModelFactory(LocalContext.current, navBackStackEntry)
val viewModel: HomeViewModel = viewModel(key = "HomeViewModel", factory = factory)
HomeScreen(
)
}
}
}
}
}
LoginScreen
@Composable
fun LoginScreen(
isNetworkAvailable: Boolean,
onNavigateToHomeScreen: (String) -> Unit,
viewModel: LoginViewModel
) {
val loading = viewModel.loading.value
val user = viewModel.user.value
Scaffold(
modifier = Modifier.fillMaxSize()
) {
if (!loading && user == null) {
Button(onClick = { viewModel.onTriggerEvent(LoginEvent.AuthStateEvent) }) {
Column(
) {
Text(text = "Log in")
}
}
}else {
user?.let {
val route = Screen.Home.route
onNavigateToHomeScreen(route)
}
}
}
}
LoginViewModel
@HiltViewModel
class LoginViewModel @Inject constructor(
private val postLogin: PostLogin,
private val connectivityManager: ConnectivityManager
) : ViewModel() {
val user: MutableState<User?> = mutableStateOf(null)
val loading = mutableStateOf(false)
val onLoad: MutableState<Boolean> = mutableStateOf(false)
fun onTriggerEvent(event: LoginEvent) {
viewModelScope.launch {
try {
when(event) {
is LoginEvent.AuthStateEvent -> {
Log.d(TAG,"Phase 1")
if (user.value == null) {
val auth: Auth = Auth([***AuthData***])
postAuth(auth)
}
}
}
}catch (e: Exception) {
Log.d(TAG, "launchJob: Exception: ${e}, ${e.cause}")
e.printStackTrace()
}
}
}
private fun postAuth(auth: Auth) {
Log.d(TAG,"Phase 2")
postLogin.execute(auth, connectivityManager.isNetworkAvailable.value).onEach { dataState ->
loading.value = dataState.loading
dataState.data?.let { data ->
user.value = data
Log.d(TAG,"Phase 3")
Log.d(TAG,"User Data File")
}
dataState.error?.let { error ->
Log.d(TAG, "postAuth: ${error}")
}
}.launchIn(viewModelScope)
}
}
LoginEvent
sealed class LoginEvent {
object AuthStateEvent: LoginEvent()
}
PostLogin
class PostLogin(
private val apiService: ApiService,
private val authDtoMapper: AuthDtoMapper,
private val userDtoMapper: UserDtoMapper
) {
fun execute(
auth: Auth,
isNetworkAvailable: Boolean
): Flow<DataState<User>> = flow {
//auth -> authDto -> InterActions -> userDto -> user
try {
emit(DataState.loading())
delay(1000)
if (isNetworkAvailable) {
val networkUser = postLoginFromNetwork(auth)
if (networkUser != null) {
emit(DataState.success(networkUser))
}else {
emit(DataState.error<User>("User data is null"))
}
}else {
emit(DataState.error<User>("Unable to connect network"))
}
}catch (e: Exception) {
emit(DataState.error<User>(e.message?: "Unknown Error"))
}
}
private suspend fun postLoginFromNetwork(auth: Auth): User {
return userDtoMapper.mapToDomainModel(apiService.login(authDtoMapper.fromDomain(auth)))
}
}
HomeScreen
@Composable
fun HomeScreen() {
Card(
modifier = Modifier.fillMaxSize()
) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "HomeScreen",
fontWeight = FontWeight.Bold,
fontSize = 40.sp
)
}
}
}
Hello, I made the above code go to HomeScreen
when login is successful by pressing the Login
button on LoginScreen
.
It was confirmed that the communication was smooth and the value was also brought.
However, when I tried debugging, I confirmed that this part was repeatedly done on Login Screen.
user?.let {
val route = Screen.Home.route
onNavigateToHomeScreen(route)
}
As you can see, when the user has a value, the screen is moved, but that part is repeatedly done, so the HomeScreen
screen glitters like a flash.
That's why I'm asking you this question. When the value changes after communication, please tell me how to move the screen.
Use the LauchedEffect
LaunchedEffect(user){
user.let {
navController.navigate("")
}
}