Home > Net >  Activity Launcher(File picker) is loading multiple times in single event - Jetpack compose
Activity Launcher(File picker) is loading multiple times in single event - Jetpack compose

Time:05-18

I am using a file picker inside a HorizontalPager in jetpack compose. When the corresponding screen is loaded while tapping the button, the launcher is triggered 2 times.

Code snippet

var openFileManager by remember {
        mutableStateOf(false)
}

if (openFileManager) {
     launcher.launch("*/*")
}

Button(text = "Upload",
        onClick = {
            openFileManager = true
    })

CodePudding user response:

The screen can draw multiple times when you click and make openFileManager true so using only condition won't prevent it from calling multiple times.

You can wrap your code with LaunchedEffect with openFileManager as a key. The LaunchedEffect block will run only when your openFileManager change.

if (openFileManager) {
    LaunchedEffect(openFileManager) {
         launcher.launch("*/*")
    }
}

CodePudding user response:

You should NEVER store such important state inside a @Composable. Such important business logic is meant to be stored in a more robust holder like the ViewModel.

ViewModel{
  var launch by mutableStateOf (false)
  private set
 
  fun updateLaunchValue(newValue: Boolean){
    launch = newValue
  }
}

Pass these to the Composable from the main activity

MyComposable(
  launchValue = viewModel.launch
  updateLaunchValue = viewModel::updateLaunchValue
)

Create the parameters in the Composable as necessary

@Comoosable
fun Uploader(launchValue: Boolean, onUpdateLaunchValue: (Boolean) -> Unit){
  LaunchedEffect (launchValue){
    if (launchValue)
      launcher.launch(...)
  }
  
  Button { // This is onClick
    onUpdateLaunchValue(true) // makes the value true in the vm, updating state
  }
}

If you think it is overcomplicated, you're in the wrong paradigm. This is the recommended AND CORRECT way of handling state in Compose, or any declarative paradigm, really afaik. This keeps the code clean, while completely separating UI and data layers, allowing controlled interaction between UI and state to achieve just the perfect behaviour for the app.

  • Related