I want to go to another screen only when the api call is finished. I’m using the below code and it works fine in splash screen (i can see the api call happening in log cat) but when i navigate and try to collect the flow in that screen nothing is showing (like the bottomsheets based on result) what is the problem here ? is there a way to achieve this? i would appreciate any help and solution.
my viewmodel:
@HiltViewModel
class MainViewModel @Inject constructor(
private val mainRepo: MainRepository,
@ApplicationContext private val context:Context
) : ViewModel() {
val statusFlow = MutableStateFlow<NetworkResult<Status>>(NetworkResult.Loading())
var status by mutableStateOf(Status())
fun getStatus(){
viewModelScope.launch {
statusFlow.emit(mainRepo.getStatus())
}
}
}
... rest of the viewmodel
splash screen:
@Composable
fun SplashScreen(navController: NavController,mainViewModel: MainViewModel = hiltViewModel()) {
Splash()
LaunchedEffect(true) {
getAllApiCalls(mainViewModel)
mainViewModel.statusFlow.collectLatest {
when(it){
is NetworkResult.Success -> {
navController.navigate(Screens.MainScreen.route) {
popUpTo(Screens.SplashScreen.route) {
inclusive = true
}
}
}
is NetworkResult.Loading -> {...}
is NetworkResult.Error -> {...}
}
}
}
}
private fun getAllApiCalls(mainViewModel: MainViewModel) {
mainViewModel.getStatus()
}
my main screen:
@Composable
fun MainScreen(
navController: NavController,
mainViewModel: MainViewModel = hiltViewModel(),
) {
Main(mainViewModel = mainViewModel)
}
@SuppressLint("CoroutineCreationDuringComposition")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Main(mainViewModel: MainViewModel) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val sheetState = rememberBottomSheetScaffoldState(
bottomSheetState = SheetState(
initialValue = SheetValue.Hidden,
skipPartiallyExpanded = false,
)
)
val drawerState = rememberDrawerState(
initialValue = DrawerValue.Closed
)
val statusResult by mainViewModel.statusFlow.collectAsState()
Log.e("TAG",statusResult.toString())
when (statusResult) {
is NetworkResult.Success -> {
mainViewModel.status = statusResult.data ?: Status()
Log.e("TAG"," hi ${mainViewModel.status.url}")
scope.launch {
if (mainViewModel.status.minVersion > VersionHelper.getVersionCode(context)!!) {
if (!sheetState.bottomSheetState.isVisible) {
drawerState.close()
mainViewModel.bottomSheetContents.value = BottomSheetContents.UPDATE
sheetState.bottomSheetState.expand()
}
return@launch
}
if (!mainViewModel.status.functional) {
if (!sheetState.bottomSheetState.isVisible) {
drawerState.close()
mainViewModel.bottomSheetContents.value =
BottomSheetContents.UNDER_CONSTRUCTION
sheetState.bottomSheetState.expand()
}
return@launch
}
if (!mainViewModel.status.reject) {
if (!sheetState.bottomSheetState.isVisible) {
drawerState.close()
mainViewModel.bottomSheetContents.value = BottomSheetContents.DISABLED_USER
sheetState.bottomSheetState.expand()
}
return@launch
}
}
}
is NetworkResult.Error -> {
Log.e("TAG", "error api statusResult : ${statusResult.message}")
LaunchedEffect(Unit) {
if (!sheetState.bottomSheetState.isVisible) {
drawerState.close()
mainViewModel.bottomSheetContents.value =
BottomSheetContents.UNDER_CONSTRUCTION
sheetState.bottomSheetState.expand()
}
}
}
is NetworkResult.Loading -> {}
}
... rest of the code
If i call the getAllApiCalls()
function in the mainscreen the problem goes away but in this way i call the apis 2 times and that would defeat the whole purpose of calling in in the SplashScreen()