Refreshing the screen

I wrote my first app. It displays a simple screen with an addition to complete. If the given answer is correct, I would like to refresh the screen to display a new calculation.
Currently, the old calculation remains, and the new one is inserted on the top.

The screen I would like:

What I see on screen after several given answers:

Here is my code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>
package com.example.calcul
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.calcul.ui.theme.CalculTheme
import kotlin.random.Random
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
CalculTheme {
MainContent()
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainContent() {
Scaffold(
topBar = {
TopAppBar(
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.primary,
),
title = {
Text("Addition")
}
)
},
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.border(2.dp, color = Color.Red)
// For text to be displayed under the bar
.padding(innerPadding)
) {
//Add()
InitializeNumbers()
}
}
}
@Composable
fun Add(fist: String, second: String) {
var haveToReset by remember {
mutableStateOf(false)
}
if (haveToReset) {
InitializeNumbers()
}
val focusRequester = remember { FocusRequester() }
var fist_number by remember { mutableStateOf(fist) }
var second_number by remember { mutableStateOf(second) }
var resultInput by remember { mutableStateOf("") }
var result by remember { mutableIntStateOf(0) }
result = fist_number.toInt() + second_number.toInt()
val maxChar: Int = 2
Spacer(modifier = Modifier.height(50.dp))
Text(
text = "$fist_number + $second_number = ",
fontSize = 50.sp
)
TextField(
value = resultInput,
singleLine = true,
// /questions/67136058/textfield-maxlength-android-jetpack-compose
onValueChange = { if (it.length <= maxChar) resultInput = it },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
keyboardActions = KeyboardActions(
onDone = {
if (resultInput.toInt() == result) {
println("OK")
haveToReset = !haveToReset
}
}
),
modifier = Modifier.focusRequester(focusRequester)
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}
@Composable
fun InitializeNumbers() {
var fist = Random.nextInt(11).toString()
var second = Random.nextInt(11).toString()
Add(fist, second)
}
@Preview(showBackground = true)
@Composable
fun AdditionPreview() {
CalculTheme {
MainContent()
}
}
</code>
<code> package com.example.calcul import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.border import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.TextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.example.calcul.ui.theme.CalculTheme import kotlin.random.Random class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { CalculTheme { MainContent() } } } } @OptIn(ExperimentalMaterial3Api::class) @Composable fun MainContent() { Scaffold( topBar = { TopAppBar( colors = TopAppBarDefaults.topAppBarColors( containerColor = MaterialTheme.colorScheme.primaryContainer, titleContentColor = MaterialTheme.colorScheme.primary, ), title = { Text("Addition") } ) }, ) { innerPadding -> Column( modifier = Modifier .fillMaxHeight() .fillMaxWidth() .border(2.dp, color = Color.Red) // For text to be displayed under the bar .padding(innerPadding) ) { //Add() InitializeNumbers() } } } @Composable fun Add(fist: String, second: String) { var haveToReset by remember { mutableStateOf(false) } if (haveToReset) { InitializeNumbers() } val focusRequester = remember { FocusRequester() } var fist_number by remember { mutableStateOf(fist) } var second_number by remember { mutableStateOf(second) } var resultInput by remember { mutableStateOf("") } var result by remember { mutableIntStateOf(0) } result = fist_number.toInt() + second_number.toInt() val maxChar: Int = 2 Spacer(modifier = Modifier.height(50.dp)) Text( text = "$fist_number + $second_number = ", fontSize = 50.sp ) TextField( value = resultInput, singleLine = true, // /questions/67136058/textfield-maxlength-android-jetpack-compose onValueChange = { if (it.length <= maxChar) resultInput = it }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), keyboardActions = KeyboardActions( onDone = { if (resultInput.toInt() == result) { println("OK") haveToReset = !haveToReset } } ), modifier = Modifier.focusRequester(focusRequester) ) LaunchedEffect(Unit) { focusRequester.requestFocus() } } @Composable fun InitializeNumbers() { var fist = Random.nextInt(11).toString() var second = Random.nextInt(11).toString() Add(fist, second) } @Preview(showBackground = true) @Composable fun AdditionPreview() { CalculTheme { MainContent() } } </code>

package com.example.calcul

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.calcul.ui.theme.CalculTheme
import kotlin.random.Random


class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        setContent {
            CalculTheme {
                 MainContent()
                }
            }
        }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainContent() {
    Scaffold(
        topBar = {
            TopAppBar(
                colors = TopAppBarDefaults.topAppBarColors(
                    containerColor = MaterialTheme.colorScheme.primaryContainer,
                    titleContentColor = MaterialTheme.colorScheme.primary,
                ),
                title = {
                    Text("Addition")
                }
            )
        },
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .fillMaxHeight()
                .fillMaxWidth()
                .border(2.dp, color = Color.Red)
                // For text to be displayed under the bar
                .padding(innerPadding)
        ) {
            //Add()
            InitializeNumbers()
        }
    }
}

@Composable
fun Add(fist: String, second: String) {

    var haveToReset by remember {
        mutableStateOf(false)
    }
    if (haveToReset) {
        InitializeNumbers()
    }

    val focusRequester = remember { FocusRequester() }

    var fist_number by remember { mutableStateOf(fist) }
    var second_number by remember { mutableStateOf(second) }
    var resultInput by remember { mutableStateOf("") }

    var result by remember { mutableIntStateOf(0) }
    result = fist_number.toInt() + second_number.toInt()

    val maxChar: Int = 2

    Spacer(modifier = Modifier.height(50.dp))
    Text(
        text = "$fist_number + $second_number = ",
        fontSize = 50.sp
    )

    TextField(
        value = resultInput,
        singleLine = true,
        // /questions/67136058/textfield-maxlength-android-jetpack-compose
        onValueChange = { if (it.length <= maxChar) resultInput = it },
        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
        keyboardActions = KeyboardActions(
            
            onDone = {
                if (resultInput.toInt() == result) {
                    println("OK")
                    haveToReset = !haveToReset
                }
            }
        ),
        modifier = Modifier.focusRequester(focusRequester)
    )
    LaunchedEffect(Unit) {
        focusRequester.requestFocus()
}
    }

@Composable
fun InitializeNumbers() {
    var fist = Random.nextInt(11).toString()
    var second = Random.nextInt(11).toString()
    Add(fist, second)
}

@Preview(showBackground = true)
@Composable
fun AdditionPreview() {
    CalculTheme {
        MainContent()
    }
}

Thanks for you help

You have a conditional recursive call in your code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>@Composable
fun Add(fist: String, second: String) {
//...
if (haveToReset) {
InitializeNumbers() // HERE IS THE RECURSIVE CALL
}
//...
}
</code>
<code>@Composable fun Add(fist: String, second: String) { //... if (haveToReset) { InitializeNumbers() // HERE IS THE RECURSIVE CALL } //... } </code>
@Composable
fun Add(fist: String, second: String) {
    //...
    if (haveToReset) {
        InitializeNumbers()  // HERE IS THE RECURSIVE CALL
    }
    //...
}

This will result in a call stack like this:

MainContent -> InitializeNumbers -> Add -> InitializeNumbers -> Add -> InitializeNumbers -> ...

Instead, your app should follow the unidirectional data flow pattern. That means that state should flow down the Composable hierarchy and events flow upwards using callback functions. In your case, delegate the state management to the parent Composable and use a callback to initialize new numbers.

First, change the signature of the Add Composable and only use the following variables:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>@Composable
fun Add(first: Int, second: Int, onReset: () -> Unit) {
val focusRequester = remember { FocusRequester() }
val maxChar: Int = remember { 2 }
val result = first + second
var resultInput by remember { mutableStateOf("") }
LaunchedEffect(first, second) { // reset input with new calculation
resultInput = ""
}
Spacer(modifier = Modifier.height(50.dp))
Text(
text = "$first + $second = ",
fontSize = 50.sp
)
//...
}
</code>
<code>@Composable fun Add(first: Int, second: Int, onReset: () -> Unit) { val focusRequester = remember { FocusRequester() } val maxChar: Int = remember { 2 } val result = first + second var resultInput by remember { mutableStateOf("") } LaunchedEffect(first, second) { // reset input with new calculation resultInput = "" } Spacer(modifier = Modifier.height(50.dp)) Text( text = "$first + $second = ", fontSize = 50.sp ) //... } </code>
@Composable
fun Add(first: Int, second: Int, onReset: () -> Unit) {

    val focusRequester = remember { FocusRequester() }
    val maxChar: Int = remember { 2 }
    val result = first + second

    var resultInput by remember { mutableStateOf("") }
    LaunchedEffect(first, second) {  // reset input with new calculation
        resultInput = ""
    }

    Spacer(modifier = Modifier.height(50.dp))
    Text(
        text = "$first + $second = ",
        fontSize = 50.sp
    )
    //...
}

Then, after completing and validating the input, call the onReset() function:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>keyboardActions = KeyboardActions(
onDone = {
if (resultInput.toInt() == result) {
println("OK")
onReset()
}
}
),
</code>
<code>keyboardActions = KeyboardActions( onDone = { if (resultInput.toInt() == result) { println("OK") onReset() } } ), </code>
keyboardActions = KeyboardActions(
    onDone = {
        if (resultInput.toInt() == result) {
            println("OK")
            onReset()
        }
    }
),

And directly call the Add Composable in your MainContent Composable like this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainContent() {
Scaffold(
//...
) { innerPadding ->
Column(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.border(2.dp, color = Color.Red)
.padding(innerPadding)
) {
var firstNumber by remember {
mutableIntStateOf(Random.nextInt(11))
}
var secondNumber by remember {
mutableIntStateOf(Random.nextInt(11))
}
Add(
first = firstNumber,
second = secondNumber,
onReset = {
firstNumber = Random.nextInt(11)
secondNumber = Random.nextInt(11)
}
)
}
}
}
</code>
<code>@OptIn(ExperimentalMaterial3Api::class) @Composable fun MainContent() { Scaffold( //... ) { innerPadding -> Column( modifier = Modifier .fillMaxHeight() .fillMaxWidth() .border(2.dp, color = Color.Red) .padding(innerPadding) ) { var firstNumber by remember { mutableIntStateOf(Random.nextInt(11)) } var secondNumber by remember { mutableIntStateOf(Random.nextInt(11)) } Add( first = firstNumber, second = secondNumber, onReset = { firstNumber = Random.nextInt(11) secondNumber = Random.nextInt(11) } ) } } } </code>
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainContent() {
    Scaffold(
        //...
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .fillMaxHeight()
                .fillMaxWidth()
                .border(2.dp, color = Color.Red)
                .padding(innerPadding)
        ) {
 
            var firstNumber by remember {
                mutableIntStateOf(Random.nextInt(11)) 
            }
            var secondNumber by remember { 
                mutableIntStateOf(Random.nextInt(11)) 
            }
            
            Add(
                first = firstNumber,
                second = secondNumber,
                onReset = {
                    firstNumber = Random.nextInt(11)
                    secondNumber = Random.nextInt(11)
                }
            )
        }
    }
}

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật