Jetpack Compose is a modern declarative UI Toolkit . In jetpack's declarative approach widgets are stateless and does not expose getter or setter function . So we cannot update UI with button.setText(String) or img.setImageBitmap()....
In Compose we build UI by defining set of Composable function. Composable function take in data and emit UI elements. So in Compose only way to update the UI is by calling the same Composable function with new Arguments. This Argument represents UI State. State in an app is any value that changes over time , this includes simple class variable to Room Database. Any time a State is updated we need to call the Composable with new State to update the UI. This is called ReComposition.
This Demo Jetpack Compose app will help you understand the basics of Jetpack Compose.
Screenshots of this App
This is our MainActivitypackage com.arun.androidtutsforu.democompose
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.arun.androidtutsforu.democompose.ui.theme.DemoComposeTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DemoComposeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
CalculateScreen()
}
}
}
}
}
@Composable
fun CalculateScreen(){
var firstNum by remember { mutableStateOf("")}
var secondNum by remember { mutableStateOf("")}
val num1 = firstNum.toIntOrNull()?:0
val num2 = secondNum.toIntOrNull()?:0
val sum = num1+num2
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "JetPack Compose Demo",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = Color.Blue
)
Spacer(modifier = Modifier.height(32.dp))
TextField(
value =firstNum ,
onValueChange ={firstNum = it} ,
label = { Text(text = "Enter First Num")}
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
value = secondNum,
onValueChange = {secondNum=it},
label = { Text(text = "Enter Second Num")}
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "The sum is $sum",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
}
}
@Composable
fun CalculateScreen(){
....
....
}
This is our Composable function . In Compose we build UI by defining set of Composable functionColumn(modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
....
....
}
we use Column to place elements vertically on the screen
var firstNum by remember { mutableStateOf("")}
var secondNum by remember { mutableStateOf("")}
mutableStateOf is an Observable type integrated with android runtime.So when we define any state as mutableStateOf , any changes to that state will schedule recomposition of every composable function that reads that state.
Composable uses remember API to store an object in memory . Stored value is returned during recomoposition. We use remember and mutableStateof to update the UI.
val value = remember{mutableStateof(default)
val value by remember{muableStateof(default)
when we use by delegates we use the following imports
import androidx.compose.runtime.getValue import androidx.compose.runtime.setValueour var firstNum,secondNum are defined as mutableStateOf with default value " ". So when its value changes in
TextField(
value =firstNum ,
onValueChange ={firstNum = it} ,
label = { Text(text = "Enter First Num")}
)
...
TextField(
value = secondNum,
onValueChange = {secondNum=it},
label = { Text(text = "Enter Second Num")}
)
remember helps us retain the State across recomposition . But when configuration changes happens (rotation of the device ) and on process death whole activity restarts and all the state will be lost. So We must use rememberSeaveble instead of remember , rememberSeaveble will survive configuration changes and process death . rememberSaveable automatically saves any value that can be saved in a Bundle. For other values we can pass a custom saver objects
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
DemoComposeTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
CalculateScreen()
}
}
}
}
}
@Composable
fun CalculateScreen(){
var firstNum by rememberSaveable{ mutableStateOf("")}
var secondNum by rememberSaveable { mutableStateOf("")}
val num1 = firstNum.toIntOrNull()?:0
val num2 = secondNum.toIntOrNull()?:0
val sum = num1+num2
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "JetPack Compose Demo",
fontWeight = FontWeight.Bold,
fontSize = 20.sp,
color = Color.Blue
)
Spacer(modifier = Modifier.height(32.dp))
TextField(
value =firstNum ,
onValueChange ={firstNum = it} ,
label = { Text(text = "Enter First Num")}
)
Spacer(modifier = Modifier.height(16.dp))
TextField(
value = secondNum,
onValueChange = {secondNum=it},
label = { Text(text = "Enter Second Num")}
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "The sum is $sum",
fontWeight = FontWeight.Bold,
fontSize = 20.sp
)
}
}
You can Download full Source code of this App From my github


Comments
Post a Comment