Jetpack Compose
These guidelines outline the best practices and conventions for building native UI with Jetpack Compose.
Modifiers
Several conventions apply to the Modifiers parameter, as mentioned below:
- The modifier parameter must be named as “modifier”.
- The modifier parameter must appear as the first optional parameter in the composable function’s parameter list.
@Composable
fun LoginButton(
modifier: Modifier = Modifier
) {}
State and Event
Following official best practices, use remember
if possible to minimize expensive calculations whenever the composable functions are recomposed.
@Composable
fun LoginButton(
modifier: Modifier = Modifier
) {
val rememberLoginState = remember { mutableStateOf(loginState) }
LoginButton(modifier) {
enabled = rememberLoginState
}
}
@Composable
fun LoginButton(
modifier: Modifier = Modifier
) {
LoginButton(modifier) {
enabled = mutableStateOf(loginState)
}
}
Conventions
Naming Unit @Composable functions as entities
The names of composable functions as entities must be a noun, but may be prefixed by descriptive adjectives written in PascalCase
.
- Naming composable functions for screens
@Composable
fun HomeScreen() {}
@Composable
fun homeScreen() {}
- Naming composable functions for widgets
@Composable
fun LoginButton() {}
@Composable
fun loginButton() {}
@Composable
fun renderLoginButton() {}
- Naming preview functions with a
Preview
suffix
@Preview(showBackground = true)
@Composable
fun HomeScreenPreview() {}
@Preview(showBackground = true)
@Composable
fun HomeScreenpreview() {}
Naming @Composable functions
The names of composable functions that return values other than Unit
must follow the standard Kotlin Coding Conventions for naming functions written in camelCase
.
- Naming @Composable functions that return values
@Composable
fun defaultStyle(): Style {
@Composable
fun DefaultStyle(): Style {
- Naming @Composable functions that
remember {}
the objects they return
The names of composable factory functions that internally remember {}
and return a mutable object must be prefixed with remember
.
@Composable
fun rememberLoginState(): LoginState = remember {
LoginState()
}
@Composable
fun createLoginState(): LoginState = remember {
LoginState()
}
Preview
functions
Ordering of annotations and -
@Preview
must be placed on top of all other annotations. -
@Composable
must be located on top of class/function definition. -
Preview
functions must be added to the bottom of the files.
@Composable
fun LoginButton() {}
@Composable
fun LogoutButton() {}
...
@Preview(showBackground = true)
...
@Composable
fun LoginButtonPreview() {}
@Preview(showBackground = true)
...
@Composable
fun LogoutButtonPreview() {}
Separating compose functions into different files
There has been no official document on when to separate composable functions into different files yet, but these methods can be followed:
Separation by commonly used
If the component in question is used by multiple composable functions, separate it into a different class file with a generic name and its own @Preview
.
@Composable
fun AppToolbar(
modifier: Modifier = Modifier
) {
...
}
@Preview
@Composable
fun AppToolbarPreview() {
AppToolbar()
}
The composable function should NOT be separated if it is not used by others
@Composable
fun HomeBottomNavigation(navController: NavController) {
...
}
@Preview
@Composable
fun HomeBottomNavigationPreview() {
HomeBottomNavigation(
navController = rememberNavController()
)
}
Separation by number of UI states
If the component in question has multiple UI states
, separate it into a different class file with its own @Preview
.
@Composable
fun CustomPizzaImage(
pizzaOrder: PizzaOrder,
modifier: Modifier = Modifier
) {
with(piazzaOrder) {
Column(modifier) {
when (pizzaChoice) {
PizzaChoice.Empty -> {
...
}
PizzaChoice.Half -> {
...
}
PizzaChoice.Full -> {
...
}
}
Text(text = pizzaName)
}
}
}
@Preview
@Composable
fun CustomPizzaImagePreview(
@PreviewParameter(PizzaOrderProvider::class) pizzaOrder: PizzaOrder
) {
CustomPizzaImage(pizzaOrder = pizzaOrder)
}
The composable function should NOT be separated if it does not have multiple UI states.
@Composable
fun OrderItem(
orderId: String,
orderCount: Int,
imageUrl: String,
modifier: Modifier = Modifier
) {
...
}
@Preview
@Composable
fun OrderItemPreview() {
OrderItem(
orderId = "1234",
orderCount = 2,
imageUrl = ""
)
}
Detekt Rules
Configuration for Compose
In Jetpack Compose
, the team follows the official Android API Guidelines
to outline the patterns, best practices, and prescriptive style guidelines for writing idiomatic
Jetpack Compose. However, some of these guidelines violate some of the default Detekt
rules.
FunctionNaming
Using PascalCase for the function naming
that violates the detekt rules:
@Composable
fun HomeScreen() {}
Configuration
Set ignoreAnnotated
to [ 'Composable' ]
.
LongParameterList
In case of having many arguments
in functions of Jetpack Compose. For example, the function for the UI widget:
@Composable
private fun HomeScreenContent(
isFirstItemLoading: Boolean,
isSecondItemLoading: Boolean,
firstList: List<FirstItem>,
secondList: List<SecondItem>,
onFirstItemClick: (FirstItem) -> Unit = {},
onSecondItemClick: (SecondItem) -> Unit = {},
onRefresh: () -> Unit = {}
) {}
Configuration
Set ignoreDefaultParameters
to true
.
MagicNumber
In case of not specifying the named parameter
. For example, when defining the code of color without a parameter name (i.e.,Color(color = 0xFFFFFFFF
):
val White = Color(0xFFFFFFFF)
Configuration
Set ignorePropertyDeclaration
to true
.
TopLevelPropertyNaming
For the Property
pattern the team also follows PascalCase from official Android API Guidelines
, but for the Constant
pattern, it’s still under team discussion.
val White = Color(0xFFFFFFFF)
Configuration
Set the following properties:
-
propertyPattern
to'(_)?[A-Za-z][A-Za-z0-9]*'
. -
constantPattern
to'[A-Z][_A-Za-z0-9]*'
.
UnusedPrivateMember
Detekt will detect the composable preview functions that have been marked with @Preview
as unused:
@Preview(showBackground = true)
@Composable
private fun HomeScreenPreview() {
HomeScreenContent()
}
Configuration
Set the following properties:
-
ignoreAnnotated
to[ 'Preview' ]
. -
active
totrue
.