title: forcing a recomposition (Android compose)
body: <p>code:</p>
  <pre><code>package com.example.saveandloadusername
  
  import android.content.Context
  import android.content.Context.MODE_PRIVATE
  import android.os.Bundle
  import android.util.Log
  import android.widget.Toast
  import androidx.activity.ComponentActivity
  import androidx.activity.compose.setContent
  import androidx.compose.foundation.layout.*
  import androidx.compose.foundation.text.KeyboardOptions
  import androidx.compose.material.*
  import androidx.compose.runtime.*
  
  import androidx.compose.ui.Alignment
  import androidx.compose.ui.Modifier
  import androidx.compose.ui.text.input.KeyboardCapitalization
  import androidx.compose.ui.unit.dp
  
  import com.example.saveandloadusername.ui.theme.SaveAndLoadUserNameTheme
  import java.io.File
  import java.io.IOException
  
  class MainActivity : ComponentActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
          setContent {
              SaveAndLoadUserNameTheme {
                  Surface(color = MaterialTheme.colors.background) {
                      MainScreen(baseContext)
                  }
              }
          }
      }
  }
  
  @Composable
  fun MainScreen(context: Context) {
      Column(
          modifier = Modifier.fillMaxSize(),
          verticalArrangement = Arrangement.Center,
          horizontalAlignment = Alignment.CenterHorizontally
      )
      {
          var name by remember { mutableStateOf(&quot;&quot;)}
  
          if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
              Text(text=&quot;Hello, give me your name :)&quot;)
          } else {
              Text(text=&quot;welcome back ${readNameFromInternalStorage(context)}&quot;)
          }
  
          Spacer(modifier = Modifier
              .height(10.dp)
              .fillMaxWidth())
  
          OutlinedTextField(
              value=name,
              onValueChange={ name = it },
              label={Text(text=&quot;Name&quot;)},
              singleLine = true,
              keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Words)
          )
  
          Spacer(modifier = Modifier
              .height(10.dp)
              .fillMaxWidth())
  
          Button(
              onClick = {
                  name = name.replace(&quot; &quot;, &quot;&quot;.replace(&quot;\n&quot;, &quot;&quot;))
                  if(name == &quot;&quot;) {
                      Toast.makeText(context, &quot;name invalid&quot;, Toast.LENGTH_SHORT).show()
                  } else {
                      Toast.makeText(context, &quot;name (${name}) saved :D&quot;, Toast.LENGTH_SHORT).show()
                      saveNameToInternalStorage(name, context)
                  }
              },
          )
          {
              Text(text=&quot;save&quot;)
          }
  
          Spacer(modifier = Modifier
              .height(10.dp)
              .fillMaxWidth())
  
          Button(
              onClick = {
                  if(checkIfNameIsEmpty(readNameFromInternalStorage(context))) {
                      Toast.makeText(context, &quot;you need to give me a name first ;)&quot;, Toast.LENGTH_SHORT).show()
                  } else {
                      Toast.makeText(
                          context,
                          &quot;the name is: '${readNameFromInternalStorage(context)}'&quot;,
                          Toast.LENGTH_SHORT
                      ).show()
                  }
  
              },
          )
          {
              Text(text=&quot;check&quot;)
          }
  
          Spacer(modifier = Modifier
              .height(10.dp)
              .fillMaxWidth())
  
          Button(onClick = { cleanNameData(context)}) {
              Text(&quot;Remove name&quot;)
          }
  
      }
  
  }
  
  private fun saveNameToInternalStorage(name: String, context: Context): Boolean {
      return try {
          context.applicationContext.openFileOutput(&quot;name.txt&quot;, MODE_PRIVATE).use { stream -&gt;
              stream.flush()
              stream.write(name.toByteArray())
              Log.i(&quot;SAVE_STATE&quot;,&quot;name ($name) written as ${name.toByteArray()}&quot;)
          }
          return true
      } catch(e: IOException) {
          e.printStackTrace()
          false
      }
  }
  
  private fun readNameFromInternalStorage(context: Context): String {
      val file = File(context.filesDir, &quot;name.txt&quot;)
      return if (file.exists()) {
          val contentOfFile = file.readBytes().decodeToString()
          Log.i(&quot;CONTENTTT&quot;, contentOfFile)
          contentOfFile
      } else {
          &quot;&quot;
      }
  }
  
  private fun checkIfNameIsEmpty(name: String): Boolean {
      return name.isEmpty()
  }
  
  private fun cleanNameData(context: Context) {
      context.applicationContext.openFileOutput(&quot;name.txt&quot;, MODE_PRIVATE).use { stream -&gt;
          stream.flush()
          Log.i(&quot;cleanNameData&quot;, &quot;Name Removed from memory&quot;)
          Toast.makeText(context, &quot;Name removed&quot;, Toast.LENGTH_SHORT).show()
      }
  }
  
  
  </code></pre>
  <p>I've created a little app to get to know android compose and I've stumbled upon a problem that I cannot solve, the Text (that is above the TextField) doesn't update after the buttons &quot;remove name&quot; or &quot;save&quot; are pressed, the text only updates when something changes in the textBox, is there a way to force a recomposition of that text manually?
  Any help appreciated :)</p>