0

I have one Composable which has one Callback function which is responsible to perform some action based on value it is observing in ViewModel. The Composable looks like.

@Composable
fun MyComposable(
    viewModel: MyViewModel = hiltViewModel(),
    navigateToSecondScreen: () -> Unit
) {
    val stateFlow by viewModel._screenState.collectAsState()
    val apiSuccess by viewModel.apiCallSuccess.observeAsState(initial = false)
    if(apiSuccess){
        navigateToSecondScreen()
    }
  }

The Composable is called in this way

MyComposable(viewModel = myViewModel, navigateToSecondScreen = {
                // action for navigation
})

The apiSuccess is a LiveData inside ViewModel whose value is updated after Api Call is success in this way

    private val _sendingOtpSuccess: MutableLiveData<Boolean> = MutableLiveData()
        val sendingOtpSuccess: LiveData<Boolean> = _sendingOtpSuccess
        viewModelScope.launch {
                    myRepository.makeApiCall(argument = argument).collect { responseState  ->
                        when (responseState) {
                            is ResponseState.Loading -> {
                                
                            }
                            is ResponseState.Success -> {
                                _sendingOtpSuccess.value = true
                                    
                            }
                            is ResponseState.Error -> {
                                
                            }
                        }
                    }
                } 

I got this error

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: co.myProject.compose, PID: 10904
    java.lang.OutOfMemoryError: Failed to allocate a 10383376 byte allocation with 6291456 free bytes and 8530KB until OOM, target footprint 47887792, growth limit 50331648

With this above code when Api Call is Success the Composable keep continue observing and after some time App gets crashed showing memory issue. What is going wrong here ? Any help will be appreciated

Satyam Gondhale
  • 1,415
  • 1
  • 16
  • 43
  • 1
    Check if [this solution](https://stackoverflow.com/a/69491725/3585796) helps you. – Phil Dukhov Mar 24 '22 at 07:39
  • Hey Thanks it is working, but need to check what made it working. Thank you so much – Satyam Gondhale Mar 24 '22 at 07:42
  • My answer is clear about the reasons: during transition from one screen to an other one, `MyComposable` is recomposed multiple times(around each frame), and each time you call `navigateToSecondScreen` which creates an other navigation route - this recursively leads to a memory leak. Please upvote the answer if it helped your. – Phil Dukhov Mar 24 '22 at 07:45
  • oops... But I still have the issue of when screen navigating to back it open again the secondScreen after pressing back – Satyam Gondhale Mar 24 '22 at 07:54
  • Your `apiCallSuccess` contains `true` when you're coming back, that's why it's happening. It can be solved in many ways. You can remove the route from the navigation stack using `popUpTo`, as showed in [documentation](https://developer.android.com/jetpack/compose/navigation#nav-to-composable) - then your view model will be freed and a new one will be created when you navigate to the same route. An other option is using a shared flow as shown [here](https://stackoverflow.com/a/71036376/3585796) - this will make sure you only react once on an event. – Phil Dukhov Mar 24 '22 at 08:06

0 Answers0