Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Android Jetpack Compose

MOSDROID
September 13, 2019

Android Jetpack Compose

Антон Зинаков, Mail.Ru Group at #MOSDROID 19 Potassium [in KasperskyLab HeadQuarter]

На текущий момент основной способ написания UI в Android — XML разметка. Такой подход тянется уже около 10 лет и имеет свои проблемы: совместимость с предыдущими версиями ОС, достаточный объем legacy в самих классах View, относительно сложно переиспользовать написанные элементы.

В докладе я расскажу про опыт использования Jetpack Compose представленного на I/O 2019 – декларативный фреймворк для создания UI с использованием Kotlin. Это большой шаг вперед и огромный задел на будущее Android: Jetpack Compose во многом решает проблемы сегодняшнего UI, упрощает и вносит современный подход в разработку.

MOSDROID

September 13, 2019
Tweet

More Decks by MOSDROID

Other Decks in Programming

Transcript

  1. User Interface today • XML & View • 2009 •

    Compatibility problems • Hard to display the same UI on different devices and Android versions
  2. User Interface today • XML & View • 2009 •

    Compatibility problems • Hard to display the same UI on different devices and Android versions • Reusability is not convenient
  3. class MosdroidActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState) setContent { Greeting() } } @Composable fun Greeting() { Text(text = "Hello, Mosdroid!") } }
  4. @Composable fun Greeting() { Align(Alignment.Center) { Text( text = "Hello,

    Mosdroid!", style = TextStyle(fontSize = 48.sp) ) } }
  5. Real example • I want to create an application with

    possibility to add persons and display added person in list • I want to separate UI elements to two independent widgets
  6. data class PersonEditorModel( val name: String = "", val buttonTitle:

    String = "Add Person", val onClick: (String) -> Unit )
  7. data class PersonEditorModel( val name: String = "", val buttonTitle:

    String = "Add Person", val onClick: (String) -> Unit ) @Composable fun PersonEditorWidget(model: PersonEditorModel) { Column { val nameState = +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = TextStyle(fontSize = 24.sp) ) ) Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } }
  8. @Composable fun PersonEditorWidget(model: PersonEditorModel) { Column { val nameState =

    +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = TextStyle(fontSize = 24.sp) ) ) Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } } Padding(16.dp) { }
  9. @Composable fun PersonEditorWidget(model: PersonEditorModel) { Padding(16.dp) { Column { val

    nameState = +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = TextStyle(fontSize = 24.sp) ) ) Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } } } FlexRow { expanded(1.0f) { } }
  10. @Composable fun PersonEditorWidget(model: PersonEditorModel) { Padding(16.dp) { Column { val

    nameState = +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = TextStyle(fontSize = 24.sp) ) ) HeightSpacer(12.dp) FlexRow { expanded(1.0f) { Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } } }
  11. @Composable fun PersonListWidget(persons: List<Person>) { Column { persons.forEachIndexed { index,

    person -> Align(Alignment.TopLeft) { Padding(16.dp) { Text( text = person.name, style = TextStyle(fontSize = 18.sp) ) } } } } }
  12. @Composable fun PersonListWidget(persons: List<Person>) { val dividerColor = Color(0xFFC6C6C6) Column

    { persons.forEachIndexed { index, person -> Align(Alignment.TopLeft) { Padding(16.dp) { Text( text = person.name, style = TextStyle(fontSize = 18.sp) ) } } if (index != persons.lastIndex) { Divider( color = dividerColor, height = 0.5.dp ) } } } }
  13. @Composable fun Dashboard(persons: MutableList<Person>) { val state = +state {

    persons } Column { PersonEditorWidget( PersonEditorModel( name = "Anton", onClick = { state.value = state.value.apply { add(Person(it)) } } )) Divider() PersonListWidget(state.value) } }
  14. private val colorGreen = Color(0xFF1B5E20.toInt()) @Composable fun MosdroidTheme(@Children children: @Composable()

    () -> Unit) { val colors = MaterialColors(primary = colorGreen) val typography = MaterialTypography( h5 = TextStyle( fontFamily = FontFamily("Roboto"), fontWeight = FontWeight.w700, fontSize = 24.sp ), h6 = TextStyle( fontFamily = FontFamily("Roboto"), fontWeight = FontWeight.w700, fontSize = 18.sp ), button = TextStyle( fontFamily = FontFamily("Roboto"), fontWeight = FontWeight.w800, fontSize = 14.sp ) ) MaterialTheme(colors = colors, typography = typography) { children() } }
  15. @Composable fun PersonEditorWidget(model: PersonEditorModel) { Padding(16.dp) { Column { val

    nameState = +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = TextStyle(fontSize = 24.sp) ) ) HeightSpacer(12.dp) FlexRow { expanded(1.0f) { Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } } }
  16. @Composable fun PersonEditorWidget(model: PersonEditorModel) { Padding(16.dp) { Column { val

    nameState = +state { EditorModel(model.name) } TextField( value = nameState.value, onValueChange = { nameState.value = it }, editorStyle = EditorStyle( textStyle = +themeTextStyle { h5 } ) ) HeightSpacer(12.dp) FlexRow { expanded(1.0f) { Button( text = model.buttonTitle, onClick = { model.onClick(nameState.value.text) } ) } } }
  17. Links • Official resource: https://developer.android.com/jetpack/compose • Jetpack Compose Principles: http://intelligiblebabble.com/compose-from-

    first-principles/ • Example: https://medium.com/q42-engineering/android-jetpack- compose-895b7fd04bf4 • Compose Readme: https://android.googlesource.com/platform/ frameworks/support/+/refs/heads/androidx-master-dev/ui/README.md
  18. Conclusion • pre-alpha • No good instruments • UI tests?

    • Functions - small UI components • Android version independent
  19. Conclusion • pre-alpha • No good instruments • UI tests?

    • Functions - small UI components • Android version independent • Less boilerplate