title: Handling commands from the viewmodel to the UI
body: <p>The peculiarity of this application is that every time a user does something (except common things like typing) the application must check with an authority that they are indeed allowed to perform that action.</p>
  <p>For example, let us say that the user wishes to see their profile (which is on the top bar)</p>
  <p>the Composable screen looks something like this:</p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@Composable
  fun HomeScreen(
      navController: NavController,
      vm: HomeViewModel = hiltViewModel()
  ) {
      val state = vm.state.value
      val scaffoldState = rememberScaffoldState()
      HomeScreen(state, scaffoldState, vm::process)
  }
  
  @Composable
  fun HomeScreen(state: HomeState, scaffoldState: ScaffoldState, event: (HomeEvent) -&gt; Unit) {
      Scaffold(
          scaffoldState = scaffoldState,
          modifier = Modifier.fillMaxSize(),
          topBar = {
              TopAppBar(
                  title = {
                      Text(&quot;Hello world&quot;)
                  },
                  actions = {
                      IconButton(onClick = {
                          event.invoke(HomeEvent.ShowProfile)
                      }) {
                          Icon(
                              painter = painterResource(id = R.drawable.ic_person),
                              contentDescription = stringResource(id = R.string.profile)
                          )
                      }
                  }
              )
          }
      ) {
      }
  }
  </code></pre>
  <p>the view model receives it like so:</p>
  <pre class="lang-kotlin prettyprint-override"><code>@HiltViewModel
  class HomeViewModel @Inject constructor(app: Application, private val checkAllowed: CheckAllowed): AndroidViewmodel(app) {
      val state = mutableStateOf(HomeState.Idle)
  
      fun process(event:HomeEvent) {
          when(event) {
              HomeEvent.ShowProfile -&gt; {
                 state.value = HomeState.Loading
                 viewModelScope.launch {
                     try {
                         val allowed = checkAllowed(Permission.SeeProfile) //use case that checks if the action is allowed
                         if (allowed) {
  
                         } else {
  
                         }
                     } finally {
                          state.value = HomeState.Idle
                     }
                 }
              }
  
          }
      }
  }
  </code></pre>
  <p>I now have to send a command to the ui, to either show a snackbar with the error or navigate to the profile page.</p>
  <p>I have read a number of articles saying that compose should have a state, and the correct way to do this is make a new state value, containing the response, and when the HomeScreen receives it , it will act appropriately and send a message back that it is ok</p>
  <p>I assume something like this :
  in the viewmodel</p>
  <pre class="lang-kotlin prettyprint-override"><code> val command = mutableStateOf&lt;HomeCommand&gt;(HomeCommand.Idle)
  
   fun commandExecuted() {
       command.value = HomeCommand.Idle
   }
  </code></pre>
  <p>and inside the HomeScreen</p>
  <pre class="lang-kotlin prettyprint-override"><code>val command = vm.command.value
  try {
      when (command) {
          is HomeCommand.ShowProfile -&gt; navController.navigate(&quot;profile_screen&quot;)
          is HomeCommand.ShowSnackbar -&gt; scaffoldState.snackbarHostState.showSnackbar(command.message, &quot;Dismiss&quot;, SnackbarDuration.Indefinite)
  
      }
  }finally {
     vm.commandExecuted()
  }
  </code></pre>
  <p>but the way I did it is using flows like so:</p>
  <p>inside the viewmodel:</p>
  <pre class="lang-kotlin prettyprint-override"><code>private val _commands = MutableSharedFlow&lt;HomeCommand&gt;(0, 10, BufferOverflow.DROP_LATEST)
  val commands: Flow&lt;HomeCommand&gt; = _commands
  </code></pre>
  <p>and inside the HomeScreen:</p>
  <pre class="lang-kotlin prettyprint-override"><code>LaunchedEffect(key1 = vm) {
      this@ExecuteCommands.commands.collectLatest { command -&gt;
          when (command) {
              is HomeCommand.ShowProfile -&gt; navController.navigate(&quot;profile_screen&quot;)
              is HomeCommand.ShowSnackbar -&gt; scaffoldState.snackbarHostState.showSnackbar(command.message, &quot;Dismiss&quot;, SnackbarDuration.Indefinite)
  
      }
  }
  </code></pre>
  <p>This seems to work, but I am afraid there may be a memory leak or something I'm missing that could cause problems</p>
  <p>Is my approach correct? Should I change it to state as in the first example? can I make it better somehow?</p>