Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Composable New World

D8a3623b157508fecdae1f8e756f362f?s=47 cmota
August 11, 2021

A Composable New World

As our Twitter streams become flooded with the release of Jetpack Compose 1.0, it's time to jump into the UI declarative world and reform the XML and all of the `findViewById` calls that exist scattered throughout the code.

Join me in this talk to see the first steps into this composable new world and build your first app (with Compose)!

D8a3623b157508fecdae1f8e756f362f?s=128

cmota

August 11, 2021
Tweet

More Decks by cmota

Other Decks in Education

Transcript

  1. A Composable new world Photo by Greg Rosenke on Unsplash

    @cafonsomota
  2. 👨💻 Android GDE 🗣 Founder @GDGCoimbra and co-founder @Kotlin_Knights ✍

    Author @rwenderlich 🎙 Podcaster wannabe 🗺 Loves travel, photography and running @cafonsomota
  3. 🖥 speakerdeck.com/cmota/a-composable-new-world 👉 github.com/cmota/unsplash-compose 🚀 github.com/cmota/kmp-a-multiplatform-triathlon @cafonsomota Materials

  4. A brief history of (android) time

  5. Android * Declarative UI Patterns (I/O’19) - https://www.youtube.com/watch?v=VsStyq4Lzxo 2008 2009

    2010 1.0 A lot of Android version in between Android Studio 2013 2014 2015 2016 2017 2018 ART RecyclerView Constraint Layout Arch Components Kotlin
  6. Android 2019 2021 Kotlin Jetpack Compose 1.0 2020 2018aaaaa 2017asda

  7. Android 2019 2021 Kotlin Jetpack Compose 1.0 2020 2018aaaaa 2017asda

  8. Jetpack Compose 1.0 Released: July 28th 2021

  9. Jetpack Compose 1.0.1 (with Kotlin 1.5.21 support)

  10. dev-reactions/it-works.gif

  11. Before we start

  12. dev-reactions/god-mode.gif

  13. 1. Git Clone • github.com/cmota/unsplash-compose 2. Download Android Studio Arctic

    Fox* • developer.android.com/studio 3. Create your Unsplash API account • unsplash.com/developers Materials * ⚠ There’s a Specific version for Mac m1
  14. Materials Unsplash Compose Android app

  15. Jetpack Compose

  16. What’s Compose? verb 1. 
 write or create (a work

    of art, especially music or poetry). "he composed the First Violin Sonata four years earlier" Definitions from Oxford Languages
  17. developer.android.com/jetpack/compose

  18. Jetpack Compose MODERN FRAMEWORK Declarative UI Less code Smaller APK’s

    Kotlin Accelerate development Intuitive Open-source Unbundled from OS
  19. Jetpack Compose MODERN FRAMEWORK Declarative UI Less code Kotlin Accelerate

    development Intuitive Open-source Smaller APK’s Unbundled from OS
  20. Declarative UI

  21. Declarative UI Imperative-UI VS

  22. Imperative UI Exercise: Implementing a List This is item 1

    This is item 2 This is item 3 This is item 4 This is item 5 This is item 6
  23. Imperative UI Exercise: Implementing a List 1. Create an activity

    MainActivity.kt
  24. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml activity_main.xml
  25. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml 3. Create a fragment MainFragment.kt
  26. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml fragment_main.xml
  27. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view RecyclerView
  28. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view 6. Create the adapter Adapter
  29. Imperative UI Exercise: Implementing a List 1. Create an activity

    2. Create the correspondent xml 3. Create a fragment 4. Create the correspondent xml 5. Create a recycler view 6. Create the adapter 7. Create the correspondent xml for the items item_adapter.xml
  30. Imperative UI Exercise: Implementing a List item_adapter.xml files created 5

    (It can be more if we want to add further customization) Lines of code written +200 (Between declarations and xml attributes)
  31. Imperative UI Exercise: Implementing a List item_adapter.xml • Time consuming

    • Error prone • Several files created • Increasing APK size • Coupled components
  32. Imperative UI Exercise: Changing the state of a view Hello

    world.
  33. How to change the access and change the state of

    a view Imperative UI Exercise: Changing the state of a view Hello world. A brief history on or
  34. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text TextView greetings = (TextView) findViewById(R.id.tv_greeting) greetings.text = “Hello world.”
  35. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text @BindView(R.id.tv_greeting) TextView greetings; greetings.text = “Hello world.” github.com/JakeWharton/butterknife
  36. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text TextView greetings = (TextView) findViewById(R.id.tv_greeting) greetings.text = “Hello world.”
  37. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text TextView greetings = findViewById(R.id.tv_greeting) greetings.text = “Hello world.”
  38. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text import kotlinx.android.synthetic.activity_main.* tv_greeting.text = “Hello world.”
  39. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text import kotlinx.android.synthetic.activity_main.* tv_greeting.text = “Hello world.” DEPRECATED
  40. Imperative UI Exercise: Changing the state of a view Hello

    world. android:Id = “@+id/tv_greeting” Text buildFeatures.viewBinding true private lateinit var binding: FragmentMainBinding override fun onCreateView( infltr: LayoutInflater, container: ViewGroup?, state: Bundle?): View { binding = FragmentMainBinding.inflate(infltr, container, false) return binding.root } binding.tvGreeting.text = “Hello world.” build.gradle
  41. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends

  42. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView

  43. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup

  44. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup extends LinearLayout

  45. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java TextView extends ImageView ViewGroup extends LinearLayout

    RelativeLayout …
  46. Imperative UI android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/View.java View.java 30407 Lines of code TextView extends

    ImageView ViewGroup extends LinearLayout RelativeLayout …
  47. Imperative UI With 30407 lines of code and several classes

    that extend it - Difficult to scale - Hard to maintain - Every change might reflect on a lot of classes - Bundled to the OS and OEM’s implementation of these components
  48. Goals Unbundle from platform releases Faster to implement new designs

    (views/components) Clarify state ownership and event handling * Adapted from declarative UI patterns (Google I/O’19) - https://www.youtube.com/watch?v=VsStyq4Lzxo&t
  49. Shifting paradigms Imperative UI Ui as a function | Kotlin

    code XML java | kotlin code Layouts Attrs Styles … Declarative ui
  50. Shifting paradigms Imperative UI What should happen How it should

    happen Declarative ui
  51. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050

  52. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI
  53. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding badge
  54. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding badge
  55. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Fire
  56. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Fire
  57. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Paper
  58. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Showing/hiding Paper
  59. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 fun updateCount(count: Int) { if (count >

    0 && !hasBadge()) { addBadge() } else if (count == 0 && hasBadge()) { removeBadge() } if (count > 99 && !hasFire()) { addFire() setBadgeText("99+") } else if (count <= 99 && hasFire()) { removeFire() } if (count > 0 && !hasPaper()) { addPaper() } else if (count == 0 && hasPaper()) { removePaper() } if (count <= 99) { setBadgeText("$count") } } Imperative UI Badge number
  60. Shifting paradigms medium.com/androiddevelopers/understanding-jetpack-compose-part-1-of-2-ca316fe39050 @Composable fun BadgedEnvelope(count: Int) { Envelope(fire=count >

    99, paper=count > 0) { if (count > 0) { Badge(text="$count") } } } Declarative UI
  61. Declarative UI Winner

  62. Compose

  63. State of compose

  64. State of compose

  65. State of compose 🤔

  66. • compose.animation • Animations library to enrich user experience •

    compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose
  67. • compose.animation • Animations library to enrich user experience •

    compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material
  68. • compose.animation • Animations library to enrich user experience •

    compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material Compose Runtime
  69. Compose compiler • Written in Kotlin • Transforms @Composable functions

    into UI • Doesn’t use the Annotation Processor • The plugin works at system/code generation level • Doesn’t impact build times • Open source • Available in AOSP Compose compiler Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material Compose Runtime android.googlesource.com/platform/frameworks/support/+/HEAD/compose/compiler
  70. Compose Runtime • Platform agnostic • DOESN’T KNOW WHAT ANDROID

    OR UI ARE • TrEE MANAGEMENT SOLUTION Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material
  71. Compose COMPILER/Runtime What this means is that Compose is, at

    its core, a general-purpose tool for managing a tree of nodes of any type. Well a “tree of nodes” describes just about anything, and as a result Compose can target just about anything. Jake Wharton - a Jetpack Compose by Any other name jakewharton.com/a-jetpack-compose-by-any-other-name/
  72. • compose.animation • Animations library to enrich user experience •

    compose.material • Ready to use material design components • compose.foundation • Building blocks • compose.ui • Ui components: layout, drawing, and input • Compose.runtime • Model, state management and core runtime • compose.compiler • Transform @composable functions and enable optimizations Jetpack compose Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose UI Compose Foundation Compose Material
  73. Compose UI toolkit • compose.ui • Handles Input Management, Drawing,

    Layouts, etc. • Compose.foundation • Contains Basic building: Row, Column, Text, iMage, etc. • Compose.material • Material design system to use on your view components • Compose.animation • Animations to use easily and out side of the box Compose compiler Compose Runtime Compose UI Toolkit (ANdroid) Compose animation Compose Foundation Compose Material Compose UI
  74. Compose UI Raspberry pi compose Compose compiler Compose Runtime Compose

    UI ANdroid Compose UI Desktop Compose UI Web Compose UI Console
  75. blog.jetbrains.com/kotlin/2021/08/compose-multiplatform-goes-alpha/

  76. Should I switch to compose?

  77. Apps in Production* *doesn’t mean they are 100% written in

    Compose
  78. Jetpack compose - before and after By Chris Banes github.com/chrisbanes/tivi

  79. medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes

    APK Size 1250 2500 3750 5000 Pre-Compose (4.49 MB) Compose (2.39 MB) 4.14 MB 2.32 MB 69 KB 347 KB 4.49MB 2.32 MB -46%
  80. medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes

    Method 12500 25000 37500 50000 Pre-Compose (40029) Compose (23689) 40029 23689 40029 methods 23689 methods -17% Count
  81. medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes

    Lines of 5000 10000 15000 20000 Pre-Compose (19478) Compose (15407) 15827 14606 19478 Lines of code 15407 lines of code Source Code 3651 801
  82. medium.com/androiddevelopers/jetpack-compose-before-and-after-8b43ba0b7d4f Jetpack compose - before and after By Chris Banes

    Build 30 60 90 120 Pre-Compose (108,71 s) Compose (76,96 s) 108,71 76,96 108,71 seconds 76,96 seconds -29% Speed
  83. YES Should I switch to compose?

  84. Compose-ready libraries

  85. github.com/google/accompanist Accompanist 📐 Insets 🍫 System UI Controller 🎨 AppCompat

    Theme Adapter 🧭✨Navigation-Animation 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts
  86. github.com/google/accompanist Accompanist 📐 Insets 🍫 System UI Controller 🎨 AppCompat

    Theme Adapter 🧭✨Navigation-Animation 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts Keyboard IME animations are now available starting on minSDK 21 (through Jetpack Compose)
  87. coil-kt.github.io/coil/compose/ Coil

  88. lottie github.com/airbnb/lottie/blob/master/android-compose.md

  89. How to Start?

  90. How to Start?

  91. Configuration android { defaultConfig { minSdk 21 … } kotlinOptions

    { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.5.10' } } build.gradle
  92. Configuration android { defaultConfig { minSdk 21 … } kotlinOptions

    { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion '1.5.10' } } build.gradle
  93. Configuration android { defaultConfig { minSdk 21 … } kotlinOptions

    { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.0.0' kotlinCompilerVersion '1.5.10' } } build.gradle
  94. Configuration android { defaultConfig { minSdk 21 … } kotlinOptions

    { jvmTarget = '1.8' useIR = true } buildFeatures { compose true } composeOptions { kotlinCompilerExtensionVersion '1.0.0' kotlinCompilerVersion '1.5.10' } } build.gradle
  95. Configuration dependencies { implementation "androidx.compose.ui:ui:1.0.0" implementation "androidx.compose.material:material:1.0.0" implementation "androidx.compose.ui:ui-tooling-preview:1.0.0" implementation

    "androidx.activity:activity-compose:1.3.1" } build.gradle
  96. Adding text XML Hello world! Kt

  97. Adding text <TextView android:id="@+id/tv_greetings" android:layout_width="wrap_content" android:layout_height=“wrap_content" android:text="Hello world!" /> XML

    Hello world! Without Compose
  98. Adding text <TextView android:id="@+id/tv_greetings" android:layout_width="wrap_content" android:layout_height=“wrap_content" android:text="Hello world!" /> XML

    Hello Android! Without Compose val greetings = findViewById(R.id.tv_greetings) greetings.text = "Hello Android!” Kt
  99. Adding text Hello world! With Compose Text(text = "Hello world!”)

    Kt
  100. Adding text Hello world! With compose @Composable fun Greeting(name: String)

    { Text(text = "Hello $name!") } Kt
  101. Adding text With compose @Composable fun Greeting(name: String) { Text(text

    = "Hello $name!") } Kt
  102. Adding text With compose @Composable fun Greeting(name: String) { Text(text

    = "Hello $name!") } Kt
  103. Adding text With compose @Composable fun Greeting(name: String) { Text(text

    = "Hello $name!") } Kt
  104. Adding text With compose @Composable fun Greeting(name: String) { Text(text

    = "Hello $name!") } Kt
  105. View Groups Hello world! XML Number of co ff ees:

    0
  106. View Groups Hello world! Without compose <?xml version="1.0" encoding="utf-8"?> <LinearLayout

    xmlns:android="http: // schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_greetings" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello world!" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Number of coffees: 0" /> </ LinearLayout> XML Number of co ff ees: 0
  107. View Groups Hello world! With compose @Composable fun Greeting(name: String)

    { Text(text = "Hello $name!") } Kt
  108. View Groups Hello world! With compose @Composable fun Greeting(name: String)

    { Text(text = "Hello $name!”) Text(text = "Number of coffees: 0") } Kt Number of co ff ees: 0
  109. View Groups Hello world! With compose @Composable fun Greeting(name: String)

    { Column { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0
  110. View Groups Hello world! With compose @Composable fun Greeting(name: String)

    { Column { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0
  111. View Groups Hello world! With compose @Composable fun Greeting(name: String)

    { Row { Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0
  112. Number of co ff ees: 0 View Groups With compose

    @Composable fun Greeting(name: String) { Column( modifier = Modifier.background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Hello world!
  113. View Groups With compose @Composable fun Greeting(name: String) { Column(

    modifier = Modifier.background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt Hello world! Number of co ff ees: 0
  114. Hello world! Number of co ff ees: 0 View Groups

    With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt
  115. Hello world! Number of co ff ees: 0 View Groups

    With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp) ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt
  116. Hello world! Number of co ff ees: 0 View Groups

    With compose @Composable fun Greeting(name: String) { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ){ Text(text = "Hello $name!") Text(text = "Number of coffees: 0") } } Kt
  117. Hello world! View Groups With compose @Composable fun Greeting(name: String)

    { Column( modifier = Modifier.fillMaxSize() .background(Color.Green) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ){ Text( text = "Hello $name!”, color = Color.White ) Text(text = "Number of coffees: 0") } } Kt Number of co ff ees: 0
  118. Hello world! Images XML Number of co ff ees: 0

  119. Hello world! Images Without compose <?xml version="1.0" encoding="utf-8"?> <LinearLayout …

    <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" android:contentDescription="@string/app_name" /> </ LinearLayout> XML Number of co ff ees: 0
  120. Hello world! Images With compose @Composable fun Greeting(name: String) {

    Column(…) { Text( text = "Hello $name!", color = Color.White ) Text(text = "Number of coffees: 0") Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) ) } } Kt Number of co ff ees: 0
  121. Hello world! Images With compose @Composable fun Greeting(name: String) {

    Column(…) { Text( text = "Hello $name!", color = Color.White ) Text(text = "Number of coffees: 0") Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) ) } } Kt Number of co ff ees: 0
  122. Hello world! Button XML Number of co ff ees: 0

    +
  123. Hello world! Button Without compose <?xml version="1.0" encoding="utf-8"?> <LinearLayout …

    <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+" /> </ LinearLayout> XML Number of co ff ees: 0 +
  124. Hello world! Button With compose @Composable fun Greeting(name: String) {

    Column(…) { … Text(text = "Number of coffees: 0") … Button(onClick = { /* TODO */ }) { Text("+") } } } Kt Number of co ff ees: 0 +
  125. Hello world! Button With compose @Composable fun Greeting(name: String) {

    Column(…) { … Text(text = "Number of coffees: 0") … Button(onClick = { /* TODO */ }) { Text("+") } } } Kt Number of co ff ees: 0 +
  126. Hello world! State Kt Number of co ff ees: 0

    +
  127. Hello world! State Without compose var count = 0 binding.tvMessage

    = getString(R.string.number_coffee, count) binding.btn_increment.setOnClickListener { count ++ } Kt Number of co ff ees: 0 +
  128. Hello world! State With compose @Composable fun Greeting(name: String) {

    Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +
  129. Hello world! State With compose @Composable fun Greeting(name: String) {

    Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +
  130. Hello world! State With compose @Composable fun Greeting(name: String) {

    Column(…) { … val count = remember { mutableStateOf(0) } Text(text = "Number of coffees taken: ${count.value}") … Button(onClick = { count.value = count.value + 1 }) { Text("+") } } } Kt Number of co ff ees: 0 +
  131. Live Demo

  132. dev-reactions/live-coding.gif

  133. Resources

  134. • Jetpack Compose samples (Google) • github.com/android/compose-samples • A curated

    list of Jetpack Compose libraries, projects, articles and resources • github.com/jetpack-compose/jetpack-compose-awesomeAnimations library to enrich user experience • Jetpack Compose Catalog • jetpackcompose.app • Jetpack/JetBrains Compose Playground • foso.github.io/Jetpack-Compose-Playground/ • Community • twitch.tv/intelligibabble • joebirch.co/tag/jetpack-compose/ • jorgecastillo.dev/ Resources
  135. A Composable new world Photo by Greg Rosenke on Unsplash

    @cafonsomota