pathway_3_interact_with_ui_and_state
Table of Contents
Pathway 3: Interact with UI and state
https://developer.android.com/courses/pathways/android-basics-compose-unit-2-pathway-3
This is a part of Android Basics with Compose course.
1. Understanding state in Compose
Optional video.
var input by remember { mutableStateOf("") }
- State can be saved:
- locally
- in the UI element
- outside
- if it is needed by other UI elements
- this is named “state hoisting”
2. Intro to tip calculator
… Tip = Gratuity (Trinkgeld in DE)
3. Intro to state in Compose
3.1 Before you begin
…
3.2 Get started
…
3.3 Get Starter Code
- clone repo and switch to
starterbranch - add
TextFieldto theTipTimeLayoutinMainActivity
3.4 Use state in Compose
…
3.5 The Composition
- If a state change happens, Compose re-executes the affected composable functions with the new state, which creates an updated UI—this is called recomposition. Compose schedules a recomposition for you.
- You use the
StateandMutableStatetypes in Compose to make state in your app observable, or tracked, by Compose. TheStatetype is immutable, so you can only read the value in it, while theMutableStatetype is mutable. You can use themutableStateOf()function to create an observableMutableState. It receives an initial value as a parameter that is wrapped in a State object, which then makes its value observable. - …
3.6 Use remember function to save state
…
@Composable fun EditNumberField(modifier: Modifier = Modifier) { var amountInput by remember { mutableStateOf("") } TextField( value = amountInput, onValueChange = { amountInput = it }, modifier = modifier ) }
- Adding the delegate's getter and setter imports lets you read and set
amountInputwithout referring to the MutableState's value property.
…
3.7 State and recomposition in action
…
3.8 Modify the appearance
@Composable fun EditNumberField(modifier: Modifier = Modifier) { var amountInput by remember { mutableStateOf("") } TextField( value = amountInput, onValueChange = { amountInput = it }, singleLine = true, label = { Text(stringResource(R.string.bill_amount)) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = modifier ) }
3.9 Display the tip amount
3.10 State hoisting
- The state (contained in the variable
amountInput) will be moved fromEditNumberFieldone level up ⇒ to theTipTimeLayout.
@Composable fun TipTimeLayout() { var amountInput by remember { mutableStateOf("") } val amount = amountInput.toDoubleOrNull() ?: 0.0 val tip = calculateTip(amount) Column( modifier = Modifier .statusBarsPadding() .padding(horizontal = 40.dp) .verticalScroll(rememberScrollState()) .safeDrawingPadding(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = stringResource(R.string.calculate_tip), modifier = Modifier .padding(bottom = 16.dp, top = 40.dp) .align(alignment = Alignment.Start) ) EditNumberField( value = amountInput, onValueChange = { amountInput = it }, modifier = Modifier .padding(bottom = 32.dp) .fillMaxWidth() ) Text( text = stringResource(R.string.tip_amount, tip), style = MaterialTheme.typography.displaySmall ) Spacer(modifier = Modifier.height(150.dp)) } } @Composable fun EditNumberField( value: String, onValueChange: (String) -> Unit, modifier: Modifier = Modifier ) { TextField( value = value, onValueChange = onValueChange, singleLine = true, label = { Text(stringResource(R.string.bill_amount)) }, keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), modifier = modifier ) }
3.11 Get the solution code
…
3.12 Conclusion
- Summary
- State in an app is any value that can change over time.
- The Composition is a description of the UI built by Compose when it executes composables. Compose apps call composable functions to transform data into UI.
- Initial composition is a creation of the UI by Compose when it executes composable functions the first time.
- Recomposition is the process of running the same composables again to update the tree when their data changes.
- State hoisting is a pattern of moving state to its caller to make a component stateless.
4. Calculate a custom tip
4.1. Before you begin
…
4.2 Get the starter code
…
4.3 Starter app overview
…
4.4 Add a tip-percentage text field
…
- add
labelparameter to theEditNumberField
…
@StringResannotation is a type-safe way to use string resources.
…
4.5 Set an action button
…
keyboardOptions = KeyboardOptions.Default.copy( keyboardType = KeyboardType.Number, imeAction = ImeAction.Next ),
4.5 Add a switch
…
Switch( checked = roundUp, onCheckedChange = onRoundUpChanged, modifier = modifier .fillMaxWidth() .wrapContentWidth(Alignment.End), )
…
4.7 Add support for landscape orientation
…
@Composable fun TipTimeLayout() { // ... Column( modifier = Modifier .padding(40.dp) .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { //... } }
4.8 Add leading icon to text fields (optional)
…
TextField( value = value, leadingIcon = { Icon(painter = painterResource(id = leadingIcon), null) }, //... )
4.9 Get the solution code
…
4.10 Conclusion
…
5. Write automated tests
5.1 Before you begin
…
5.2 Get the starter code
…
5.3 Automated tests
- Type of automated tests
- Local tests
- Local tests are a type of automated test that directly test a small piece of code to ensure that it functions properly. With local tests, you can test functions, classes, and properties.
- Local tests are executed on your workstation, which means they run in a development environment without the need for a device or emulator.
- Instrumentation tests
- An instrumentation test is a UI test.
- When you run an instrumentation test on Android, the test code is actually built into its own Android Application Package (APK) like a regular Android app.
…
@VisibleForTestingannotation …
…
5.4 Write a local test
Local tests directly test methods from the app code, so the methods to be tested must be available to the testing classes and methods. So:
- ⇒ designate
privatemethods asinternal - add
@VisibleForTestingannotation- this makes the method public, but only for testing purposes
The following list of concepts apply to local and instrumentation tests:
- Write automated tests in the form of methods.
- Annotate the method with the @Test annotation. This lets the compiler know that the method is a test method and runs the method accordingly.
- Ensure that the name clearly describes what the test tests for and what the expected result is.
- Test methods don't use logic like regular app methods. They aren't concerned with how something is implemented. They strictly check an expected output for a given input. That is to say, test methods only execute a set of instructions to assert that an app's UI or logic functions correctly. You don't need to understand what this means yet because you see what this looks like later, but remember that test code may look quite different from the app code that you're used to.
- Tests typically end with an assertion, which is used to ensure that a given condition is met. Assertions come in the form of a method call that has assert in its name. For example: the
assertTrue()assertion is commonly used in Android testing.
…
5.5 Write an instrumentation test
- usually located in
src/androidTest/java
…
5.6 Get the solution code
…
5.7 Conclusion
Summary:
- What automated tests are.
- Why automated tests are important.
- The difference between local tests and instrumentation tests
- Fundamental best practices for writing automated tests.
- Where to find and place local and instrumentation test classes in an Android project.
- How to create a test method.
- How to create local and instrumentation test classes.
- How to make assertions in local and instrumentation tests.
- How to use test rules.
- How to use
ComposeTestRuleto launch the app with a test. - How to interact with composables in an instrumentation test.
- How to run tests.
6. Project: Create an Art Space app
6.1 Before you begin
…
6.2 Build static UI with composables
…
6.3 Make the app interactive
…
6.4 Challenge: Build for different screen sizes
…
6.5 Good luck!
…
7. What's next?
…
pathway_3_interact_with_ui_and_state.txt · Last modified: by kalaschnikow
