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

Reactive UI in Android (Jetpack compose)

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Reactive UI in Android (Jetpack compose)

In Google IO 2019, Google revealed Jetpack compose, the future of UI toolkit in Kotlin.
In this talk, we're going to see what were the reasons Google decided we need a new UI toolkit, how to use it, and what problems it resolves.

Avatar for Gil Goldzweig

Gil Goldzweig

December 19, 2019
Tweet

More Decks by Gil Goldzweig

Other Decks in Programming

Transcript

  1. Jetpack compose @Composable fun Greeting(name: String) { Text("Hello: $name") }

    Declarative UI • Take data as input • Emits UI hierarchy when invoked
  2. Composable function Compiler plugin @Composable fun Greeting(name: String) { Text("Hello:

    $name") Text("Hello: $name") } Instructions tree Greeting Text Text
  3. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { } } } Surface Ripple Button
  4. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { } } } } Surface Ripple Clickable Button
  5. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { Container(padding = paddings) { } } } } } Surface Ripple Clickable Container Button
  6. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { Container(padding = paddings) { Text(text) } } } } } Surface Ripple Clickable Container Text Button
  7. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { Container(padding = paddings) { Text(text) } } } } } Surface Ripple Clickable Container Text ImageButton
  8. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { Container(padding = paddings) { Image(image) } } } } } Surface Ripple Clickable Container Image ImageButton
  9. @Composable fun Button(text, onClick) { Surface(shape, color, border, elevation) {

    Ripple(color = rippleColor) { Clickable(onClick = onClick) { Container(padding = paddings) { Image(image) } } } } } Surface Ripple Clickable Container ImageButton Image
  10. Spinner Item Clicked Selection changed We get notified Item Clicked

    We get notified UI changes Selection updated UI changes Change selection? Current Compose
  11. @Composable fun Counter() { val count = state { 0

    } } Reactive data flow Should be treated as an “observer”
  12. @Composable fun Counter() { val count = state { 0

    } Column { } } Reactive data flow
  13. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") } } Reactive data flow
  14. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) } } Reactive data flow
  15. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow
  16. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow
  17. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow
  18. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow
  19. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow Single source of truth
  20. @Composable fun Counter() { val count = state { 0

    } Column { Text("Counter demo") Button(text = "Add", onClick = { count.value++ }) Button(text = "Subtract", onClick = { count.value-- }) Text("Clicks: ${count.value}") } } Reactive data flow
  21. @Model @Model data class NewsModel( var title: String, var auther:

    String, var imageUrl: String ) data class NewsHolder(var news: List<NewsModel>)
  22. @Model @Model data class NewsModel( var title: String, var auther:

    String, var imageUrl: String ) @Model data class NewsHolder(var news: List<NewsModel>)
  23. @Model @Composable fun NewsItem(model: NewsModel) { Row { Image(url =

    model.imageUrl) Column { Text(model.title) } } }
  24. @Model @Composable fun NewsItem(model: NewsModel) { Row { Image(url =

    model.imageUrl) Column { Text(model.title) Text(model.auther, style = TextStyle(Color.Gray)) } } }
  25. @Model @Composable fun NewsFeed(holder: NewsHolder) { VerticalScroller { Column {

    holder.news.forEach { newsModel -> NewsItem(newsModel) } } } }
  26. @Model @Composable fun NewsFeed(holder: NewsHolder) { VerticalScroller { Column {

    holder.news.forEach { newsModel -> NewsItem(newsModel) Divider(height = 1.dp) } } } }
  27. Jetpack compose var newsHolder: NewsHolder override fun onCreate(savedState: Bundle?) {

    super.onCreate(savedState) setContent { NewsFeed(newsHolder) } }