0

I'm developing a fitness app and I use a wrapper around some data classes that contains information shared by all the screens , like info for the current user , what settings are used by the app etc., My initial idea was to retrieve this information from storage every time the screen is presented to the user. I decided to create a class AppStateManager that contains a SharedFlow with the app state , and each viewModel would collect that state , this would help when the user will make some changes to the settings because the viewModels would collect the most up to date version.My questions are there any way to make it lifecycle aware and also if there is a cleaner alternative to this ?

This is how I trigger the retrieval of the app state

 override fun onCreate(savedInstanceState : Bundle?) {
    super.onCreate(savedInstanceState)
    userUid = intent.getStringExtra("USER_UID") ?: guestProfile.uid

    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.CREATED) {
            appStateManager.initAppState(userUid , lifecycleScope.coroutineContext)


        }
    }

    setContent {
        WorkoutCompanionTheme {

            val databaseScreenViewModel = hiltViewModel<DatabaseScreenViewModel>().apply {
                this.beginListeningToAppStateChanges()
            }
            val profileViewModel = hiltViewModel<ProfileViewModel>().apply {
                this.beginListeningToAppStateChanges()
            }
            val trainingProgramViewModel = hiltViewModel<TrainingProgramViewModel>().apply {
                this.beginListeningToAppStateChanges()
            }
            val homeViewModel = hiltViewModel<HomeViewModel>().apply {
                this.beginListeningToAppStateChanges()
            }

            MainNavigation.MainNavigation(
              databaseScreenViewModel = databaseScreenViewModel,
                profileViewModel = profileViewModel,
                trainingProgramViewModel = trainingProgramViewModel,
                homeViewModel= homeViewModel,
                startOnBoardFlow = {
                    startEntryActivity()
                }
            )
        }
    }
}

this is the Manager Class

class AppStateManager @Inject constructor(private val workoutRepository : WorkoutRepository ,
                                      @Testing
                                      private val profileRepository : ProfileRepository ,) {


private val _appState = MutableSharedFlow<WorkoutCompanionAppState>(replay = 1 , extraBufferCapacity = 0 , onBufferOverflow = BufferOverflow.SUSPEND )
val appState = _appState.onEach { Log.d("Test" ,it.toString()) }


fun initAppState(userUid : String ,context : CoroutineContext){
    CoroutineScope(context = context).launch{
        val state = getAppState(userUid) / /function to build from storage the app state , i didn't include the code but is inside the app stateManager
        if(state == null){
            Log.d("Test" , "Failed to retrieve App State")

        }

        state?.let {
            Log.d("Test" , "Emission from manager")
            _appState.emit(it)
            Log.d("Test" , "app state listeners  = ${_appState.subscriptionCount.value}")
        }

    }.invokeOnCompletion {
        Log.d("Test" , "Init Completed")
    }


}

fun updateAppState(appState : WorkoutCompanionAppState,context : CoroutineContext){
    Log.d("Test" , "Update called")
    CoroutineScope(context).launch {
        _appState.emit(appState)
    }.invokeOnCompletion {
        Log.d("Test" , "update Completed")
    }
}

}

this is the function called by the viewModels

fun beginListeningToAppStateChanges() {
    viewModelScope.launch{

        appStateManager.appState.collectLatest{
            _appState.update { it }
        }
    }
}
  • Any particular reason for using SharedFlow instead of StateFlow(collectAsStateWithLifecycle())? – TheLibrarian Aug 28 '23 at 16:56
  • I have to annotate the viewModel function with @Composable and i also thought that sharedFlow is more suitable for this case – MCDragusanu Aug 28 '23 at 17:02
  • I know the name would suggest that but in this case StateFlow would behave the same. Also what do you mean that you have to annotate ViewModel function with Composable? – TheLibrarian Aug 28 '23 at 17:07
  • i want to listen to those changes inside the viewModel , because some screens are not directly influenced by that state , just the business logic would change based on that – MCDragusanu Aug 28 '23 at 17:14

0 Answers0