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

Jetpack Compose - The Future of Android Development (Extended)

Jetpack Compose - The Future of Android Development (Extended)

In this talk, we take a glimpse at what Jetpack Compose is in a nutshell, how we can start building an app with it, and how we can introduce it to an existing project. The talk includes 2 demo projects.
Presented at a Webuni Android webinar on 2022.04.20., online, in Hungarian.
Event:
https://www.linkedin.com/posts/webuni_a-jetpack-compose-teljesen-%C3%A1talak%C3%ADthatja-activity-6922083968951406592-t44m

Video:
https://youtu.be/gQBOYHHHBhA?t=114

Az előadásban megnézzük, hogy mi is az a Jetpack Compose dióhéjban, és hogy hogy működik, valamint hogy hogy kezdhetünk el dolgozni vele új és meglévő projectekben, 2 példaproject bemutatásával.
Az előadás a 2022.04.20-i Webuni Android webináriumon hangzott el magyarul.
https://youtu.be/gQBOYHHHBhA?t=114

István Juhos

April 20, 2022
Tweet

More Decks by István Juhos

Other Decks in Programming

Transcript

  1. Webuni webinar – @stewemetal
    stewemetal
    The Future of Android Development
    István Juhos
    Jetpack Compose

    View full-size slide

  2. Webuni webinar – @stewemetal
    How we write UI now?
    • View objects inflated from XML layout files
    • For more than 10 years now 🗓

    View full-size slide

  3. Webuni webinar – @stewemetal
    How we write UI now?
    • View objects inflated from XML layout files
    • For more than 10 years now 🗓
    • Tons and tons of other UI-related XMLs
    • Drawables/colors + selectors
    • Themes + styles
    • Custom styling attributes

    View full-size slide

  4. Webuni webinar – @stewemetal
    How we write UI now?
    • View objects inflated from XML layout files
    • For more than 10 years now 🗓
    • Tons and tons of other UI-related XMLs
    • Drawables/colors + selectors
    • Themes + styles
    • Custom styling attributes
    • View Binding / Data Binding
    • Code generation and a pinch of pixie dust… ✨
    • @BindingAdapters

    View full-size slide

  5. Webuni webinar – @stewemetal
    Imperative 👑

    View full-size slide

  6. Webuni webinar – @stewemetal
    Imperative 👑
    “Imperative programming focuses on
    describing how a program operates step
    by step, rather than on high-level
    descriptions of its expected results.”
    - Wikipedia

    View full-size slide

  7. Webuni webinar – @stewemetal
    Imperative 👑
    • Objects created exactly how we declare them
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:paddingVertical="8dp"
    android:paddingHorizontal="16dp"
    >
    android:id="@+id/itemText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:textSize="16sp"
    android:textColor="@color/grey"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@id/itemForwardArrow"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Test view item"
    />
    android:id="@+id/itemForwardArrow"
    android:layout_width="40dp"
    android:layout_height="40dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:src="@drawable/ic_chevron_right"
    app:tint="@color/grey"
    />

    inflate

    View full-size slide

  8. Webuni webinar – @stewemetal
    Declarative 📣
    The Future (is now!)

    View full-size slide

  9. Webuni webinar – @stewemetal
    Declarative 📣
    • ❌ Writing how the UI should be built
    • ✅ Writing what the UI should look like, and
    let the framework figure out how to achieve the
    result
    ConstraintLayout(
    modifier = Modifier
    .background(MaterialTheme.colors.background)
    .height(60.dp)
    .fillMaxWidth()
    .padding(horizontal = 16.dp, vertical = 8.dp),
    ) {
    Text(
    text = item.text,
    color = Grey,
    )
    Icon(
    painterResource(id = drawable.ic_chevron_right),
    )
    }
    * Not actual working code!
    *

    View full-size slide

  10. Webuni webinar – @stewemetal
    What is Compose?

    View full-size slide

  11. Webuni webinar – @stewemetal
    What is Compose?
    • A general-purpose, multiplatform compiler and
    runtime for managing a tree of nodes of any
    type
    https://jakewharton.com/a-jetpack-compose-by-any-other-name/

    View full-size slide

  12. Webuni webinar – @stewemetal
    What is Compose?
    • A general-purpose, multiplatform compiler and
    runtime for managing a tree of nodes of any
    type
    AND ALSO
    • A UI toolkit and DSL to render app UI on
    Android and Desktop
    https://jakewharton.com/a-jetpack-compose-by-any-other-name/

    View full-size slide

  13. Webuni webinar – @stewemetal
    What is Compose UI?
    • Declarative
    • Like React (Native), Flutter, and SwiftUI
    • Component-based
    • Unbundled
    • Kotlin-only
    • The UI is a function of the current UI state

    View full-size slide

  14. Webuni webinar – @stewemetal
    • Declarative
    • Like React (Native), Flutter, and SwiftUI
    • Component-based
    • Unbundled
    • Kotlin-only
    • The UI is a function of the current UI state
    f(state) UI
    =
    What is Compose UI?

    View full-size slide

  15. Webuni webinar – @stewemetal
    • We can use Composable functions to describe
    UI components based on the current UI state
    • Two-way interoperability
    • Works with existing View-based UI and vice versa
    • AndroidView composable for Views in Compose
    • ComposeView for Composables in Views
    What is Compose UI?
    f(state) UI
    =

    View full-size slide

  16. Webuni webinar – @stewemetal
    A simple list – View vs. Compose
    Check out the first demo project here:
    https://github.com/stewemetal/android-view-vs-compose

    View full-size slide

  17. Webuni webinar – @stewemetal
    A simple list – Android View

    View full-size slide

  18. Webuni webinar – @stewemetal
    A simple list – Android View
    ConstraintLayout

    View full-size slide

  19. Webuni webinar – @stewemetal
    A simple list – Android View
    MaterialToolbar
    RecyclerView

    View full-size slide

  20. Webuni webinar – @stewemetal
    A simple list – Android View
    List item view…
    List item view…

    View full-size slide

  21. Webuni webinar – @stewemetal
    A simple list – Android View
    List item view

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:paddingVertical="8dp"
    android:paddingHorizontal="16dp“>
    android:id="@+id/itemText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginEnd="16dp"
    android:textSize="16sp"
    android:textColor="@color/grey"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@id/itemForwardArrow"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Test view item“/>
    android:id="@+id/itemForwardArrow"
    android:layout_width="40dp"
    android:layout_height="40dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="ContentDescription"
    android:src="@drawable/ic_chevron_right"
    app:tint="@color/grey“/>

    - layout_item.xml

    View full-size slide

  22. Webuni webinar – @stewemetal
    A simple list – Android View
    Layout of a Fragment - fragment_view.xml

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    android:id="@+id/toolbar"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:title="View implementation"
    style="@style/Theme.ComposeDemo.AppBarOverlay"/>
    android:id="@+id/list"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/toolbar"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>

    View full-size slide

  23. Webuni webinar – @stewemetal
    A simple list – Android View
    Fragment - ViewFragment.kt
    class ViewFragment : Fragment() {
    lateinit var adapter: ViewItemAdapter
    override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?,
    ): View =
    inflater.inflate(R.layout.fragment_view, container, false)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    adapter = ViewItemAdapter()
    val list = view.findViewById(R.id.list)
    list.adapter = adapter
    adapter.submitList(
    mutableListOf().apply {
    (1..30).forEach {
    add(Item("View item $it"))
    }
    }
    )
    }
    }

    View full-size slide

  24. Webuni webinar – @stewemetal
    A simple list – Android View
    Adapter - ViewItemAdapter.kt
    class ViewItemAdapter : ListAdapter(ItemDiffUtil()) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder =
    ItemViewHolder(
    LayoutInflater.from(parent.context)
    .inflate(R.layout.layout_item, parent, false)
    )
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
    holder.bind(getItem(position))
    }
    inner class ItemViewHolder(itemView: View) : ViewHolder(itemView) {
    private val itemText: TextView = itemView.findViewById(R.id.itemText)
    fun bind(item: Item) {
    itemText.text = item.text
    }
    }
    }
    class ItemDiffUtil : DiffUtil.ItemCallback() {
    override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean {
    return oldItem == newItem
    }
    override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean {
    return oldItem == newItem
    }
    }

    View full-size slide

  25. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose

    View full-size slide

  26. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose

    View full-size slide

  27. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    ComposeView
    (interoperability)

    View full-size slide

  28. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    Composable
    Composable
    Composable

    View full-size slide

  29. Webuni webinar – @stewemetal
    Interoperability - fragment_compose.xml

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.compose.ComposeFragment">
    android:id="@+id/composeView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

    A simple list – Jetpack Compose

    View full-size slide

  30. Webuni webinar – @stewemetal
    Interoperability - fragment_compose.xml
    A simple list – Jetpack Compose

    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.compose.ComposeFragment">
    android:id="@+id/composeView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

    android:id="@+id/composeView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
    Interoperability with Views

    View full-size slide

  31. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    }
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...

    View full-size slide

  32. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...
    }
    @Composable
    fun ListItem(
    )
    f()

    View full-size slide

  33. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    }
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...
    f(state)
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...
    }

    View full-size slide

  34. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...
    }
    f(state) UI
    =
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...
    }

    View full-size slide

  35. Webuni webinar – @stewemetal
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    }
    @Composable
    fun ListItem(
    item: Item,
    ) {
    // ...

    View full-size slide

  36. Webuni webinar – @stewemetal
    @Composable
    fun ListItem(
    item: Item,
    ) {
    ConstraintLayout(
    modifier = Modifier
    .background(MaterialTheme.colors.background)
    .height(60.dp)
    .fillMaxWidth()
    .padding(horizontal = 16.dp, vertical = 8.dp),
    ) {
    // ...
    }
    A simple list – Jetpack Compose
    List item composable - ListItem.kt

    View full-size slide

  37. Webuni webinar – @stewemetal
    @Composable
    fun ListItem(
    item: Item,
    ) {
    ConstraintLayout(
    modifier = Modifier
    .background(MaterialTheme.colors.background)
    .height(60.dp)
    .fillMaxWidth()
    .padding(horizontal = 16.dp, vertical = 8.dp),
    ) {
    val (text, chevron) = createRefs()
    Text(
    text = item.text,
    color = Grey,
    fontSize = 16.sp,
    modifier = Modifier
    .constrainAs(text) {
    top.linkTo(parent.top)
    start.linkTo(parent.start)
    end.linkTo(chevron.start)
    bottom.linkTo(parent.bottom)
    width = Dimension.fillToConstraints
    },
    )
    Icon(
    painterResource(id = drawable.ic_chevron_right),
    tint = Grey,
    contentDescription = "Item arrow forward",
    modifier = Modifier
    .constrainAs(chevron) {
    top.linkTo(parent.top)
    start.linkTo(text.end, margin = 16.dp)
    end.linkTo(parent.end)
    bottom.linkTo(parent.bottom)
    width = Dimension.value(40.dp)
    height = Dimension.value(40.dp)
    },
    )
    }
    A simple list – Jetpack Compose
    List item composable - ListItem.kt

    View full-size slide

  38. Webuni webinar – @stewemetal
    @Composable
    fun ListItem(
    item: Item,
    ) {
    ConstraintLayout(
    modifier = Modifier
    .background(MaterialTheme.colors.background)
    .height(60.dp)
    .fillMaxWidth()
    .padding(horizontal = 16.dp, vertical = 8.dp),
    ) {
    val (text, chevron) = createRefs()
    Text(
    text = item.text,
    color = Grey,
    fontSize = 16.sp,
    modifier = Modifier
    .constrainAs(text) {
    top.linkTo(parent.top)
    start.linkTo(parent.start)
    end.linkTo(chevron.start)
    bottom.linkTo(parent.bottom)
    width = Dimension.fillToConstraints
    },
    )
    Icon(
    painterResource(id = R.drawable.ic_chevron_right),
    tint = Grey,
    contentDescription = "Item arrow forward",
    modifier = Modifier
    .constrainAs(chevron) {
    top.linkTo(parent.top)
    start.linkTo(text.end, margin = 16.dp)
    end.linkTo(parent.end)
    bottom.linkTo(parent.bottom)
    width = Dimension.value(40.dp)
    height = Dimension.value(40.dp)
    },
    )
    }
    A simple list – Jetpack Compose
    List item composable - ListItem.kt
    val (text, chevron) = createRefs()
    Text(
    text = item.text,
    color = Grey,
    fontSize = 16.sp,
    modifier = Modifier
    .constrainAs(text) {
    top.linkTo(parent.top)
    start.linkTo(parent.start)
    end.linkTo(chevron.start)
    bottom.linkTo(parent.bottom)
    width = Dimension.fillToConstraints
    },
    )

    View full-size slide

  39. Webuni webinar – @stewemetal
    @Composable
    fun ComposeContent() {
    ComposeDemoTheme {
    Scaffold(
    topBar = {
    TopAppBar(
    title = { Text("Compose implementation") },
    )
    },
    content = {
    LazyColumn {
    items((1..30).toList()) {
    ListItem(Item("Compose item $it"))
    }
    }
    },
    )
    }
    }
    A simple list – Jetpack Compose
    Content composable - ComposeContent.kt

    View full-size slide

  40. Webuni webinar – @stewemetal
    @Composable
    fun ComposeContent() {
    ComposeDemoTheme {
    Scaffold(
    topBar = {
    TopAppBar(
    title = { Text("Compose implementation") },
    )
    },
    content = {
    LazyColumn {
    items((1..30).toList()) {
    ListItem(Item("Compose item $it"))
    }
    }
    },
    )
    }
    }
    A simple list – Jetpack Compose
    Content composable - ComposeContent.kt
    LazyColumn {
    items((1..30).toList()) {
    ListItem(Item("Compose item $it"))
    }
    }
    The equivalent of a RecyclerView + Adapter

    View full-size slide

  41. Webuni webinar – @stewemetal
    @Composable
    fun ComposeContent() {
    ComposeDemoTheme {
    Scaffold(
    topBar = {
    TopAppBar(
    title = { Text("Compose implementation") },
    )
    },
    content = {
    LazyColumn {
    items((1..30).toList()) {
    ListItem(Item("Compose item $it"))
    }
    }
    },
    )
    }
    }
    A simple list – Jetpack Compose
    Content composable - ComposeContent.kt

    View full-size slide

  42. Webuni webinar – @stewemetal
    Fragment - ComposeFragment.kt
    class ComposeFragment : Fragment() {
    override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?,
    ): View =
    inflater.inflate(R.layout.fragment_compose, container, false)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    view.findViewById(R.id.composeView)
    .apply {
    setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
    setContent {
    ComposeContent()
    }
    }
    }
    }
    A simple list – Jetpack Compose

    View full-size slide

  43. Webuni webinar – @stewemetal
    Fragment - ComposeFragment.kt
    A simple list – Jetpack Compose
    class ComposeFragment : Fragment() {
    override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?,
    ): View =
    inflater.inflate(R.layout.fragment_compose, container, false)
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    view.findViewById(R.id.composeView)
    .apply {
    setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
    setContent {
    ComposeContent()
    }
    }
    }
    }
    view.findViewById(R.id.composeView)
    .apply {
    setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)
    setContent {
    ComposeContent()
    }
    }
    Interoperability with Views

    View full-size slide

  44. Webuni webinar – @stewemetal
    A simple list – View vs. Compose
    • View
    • Imperative
    • 2 layout XMLs
    • Binding code in a Fragment
    • RecyclerView adapter
    • Compose
    • Declarative
    • 2 composable functions in
    Kotlin
    • 1 layout in XML (interop)
    • Interop code in a Fragment

    View full-size slide

  45. Webuni webinar – @stewemetal
    • Start here, please 🙏
    Thinking in Compose
    https://developer.android.com/jetpack/compose/mental-model

    View full-size slide

  46. Webuni webinar – @stewemetal
    • UI components in Kotlin – as Composable functions
    • Themes in Kotlin – as Composable functions
    • and objects in the composition
    • Value resources in Kotlin
    • Drawables, strings, dimensions etc. can still come from
    the usual XML sources thanks to interop features
    • The UI is composed based on the current state and
    recomposed when a new state is provided
    Thinking in Compose UI

    View full-size slide

  47. Webuni webinar – @stewemetal
    • Initial composition
    • Calling Composables for the first time
    • Keeping track of the Composition
    Composition, recomposition
    https://developer.android.com/jetpack/compose/lifecycle

    View full-size slide

  48. Webuni webinar – @stewemetal
    • Initial composition
    • Calling Composables for the first time
    • Keeping track of the Composition
    • Recomposition
    • When the app state changes, Compose re-executes
    composables and updates the Composition
    Composition, recomposition
    https://developer.android.com/jetpack/compose/lifecycle

    View full-size slide

  49. Webuni webinar – @stewemetal
    • Initial composition
    • Calling Composables for the first time
    • Keeping track of the Composition
    • Recomposition
    • When the app state changes, Compose re-executes
    composables and updates the Composition
    Composition, recomposition
    https://developer.android.com/jetpack/compose/lifecycle

    View full-size slide

  50. Webuni webinar – @stewemetal
    • Use Composable functions to describe UI
    component hierarchies based on state data
    that can change over time
    UI state in Compose UI
    @Composable
    fun CustomButton(
    text: String,
    loading: Boolean,
    enabled: Boolean,
    onClick: () -> Unit,
    ) { . . . }

    View full-size slide

  51. Webuni webinar – @stewemetal
    • Use Composable functions to describe UI
    component hierarchies based on state data
    that can change over time
    CustomButton(
    // . . .
    loading = false,
    enabled = false,
    )
    UI state in Compose UI
    Custom Button

    View full-size slide

  52. Webuni webinar – @stewemetal
    • Use Composable functions to describe UI
    component hierarchies based on state data
    that can change over time
    CustomButton(
    // . . .
    loading = false,
    enabled = true,
    )
    UI state in Compose UI
    Custom Button

    View full-size slide

  53. Webuni webinar – @stewemetal
    • Use Composable functions to describe UI
    component hierarchies based on state data
    that can change over time
    CustomButton(
    // . . .
    loading = true,
    enabled = true,
    )
    UI state in Compose UI

    View full-size slide

  54. Webuni webinar – @stewemetal
    A life-like project

    View full-size slide

  55. Webuni webinar – @stewemetal
    A life-like project (🐴)

    View full-size slide

  56. Webuni webinar – @stewemetal
    How does Compose fit into our lives (and code)?
    Let’s find out!
    https://github.com/stewemetal/composehydrationtracker
    A life-like project (🐴)

    View full-size slide

  57. Webuni webinar – @stewemetal
    Existing project? No problem!
    • Composables in existing views
    • Activities
    • Fragments
    • Views in a Composition
    • Two-way interoperability
    • Compose works well with existing View-based UI
    • We can reuse our existing (custom) UI elements

    View full-size slide

  58. Webuni webinar – @stewemetal
    Existing project? No problem!
    • Composables in existing views
    • Activities
    • Fragments
    • Views in a Composition
    • Two-way interoperability
    • Compose works well with existing View-based UI
    • We can reuse our existing (custom) UI elements
    • Migrate at your own pace and educate your team!

    View full-size slide

  59. Webuni webinar – @stewemetal
    📚Resources for learning📚

    View full-size slide

  60. Webuni webinar – @stewemetal
    Resources
    • The official docs
    • https://developer.android.com/jetpack/compose/documentation
    • https://developer.android.com/jetpack/compose/mental-model
    • https://developer.android.com/jetpack/compose/state
    • https://developer.android.com/jetpack/compose/lifecycle
    • Android Developers videos
    • https://www.youtube.com/c/AndroidDevelopers/search?query=co
    mpose

    View full-size slide

  61. Webuni webinar – @stewemetal
    Resources
    • The Compose Runtime, Demystified
    • Leland Richardson, KotlinConf ‘19
    • https://youtu.be/6BRlI5zfCCk

    View full-size slide

  62. Webuni webinar – @stewemetal
    Resources
    • Jetpack Compose internals – Jorge Castillo
    • https://jorgecastillo.dev/book/
    • Pretty theory-heavy!

    View full-size slide

  63. Webuni webinar – @stewemetal
    Resources
    • Jetpack Compose basics codelab
    • https://developer.android.com/codelabs/jetpack-
    compose-basics

    View full-size slide

  64. Webuni webinar – @stewemetal
    Resources
    • Jetpack Compose Samples
    • https://github.com/android/compose-samples

    View full-size slide

  65. Webuni webinar – @stewemetal
    Resources
    • Android Developers Backstage (ADB) podcast
    • https://adbackstage.libsyn.com/
    • Starting with EP 164
    • https://adbackstage.libsyn.com/episode-164-jetpack-
    compose-compilation

    View full-size slide

  66. Webuni webinar – @stewemetal
    There’s so much more to learn about!
    • Compose lifecycle and how composition works
    • State handling
    • Side effects
    • Navigation
    • Animations
    • Accessibility
    • Custom theming
    • Integration testing
    • . . .

    View full-size slide

  67. Webuni webinar – @stewemetal
    stewemetal
    • Less code with the declarative approach
    • Faster iteration, faster implementation
    • Easier UI testing
    • Existing code/resources supported
    Photo by Xavi Cabrera
    The Future of Android Development
    István Juhos
    Jetpack Compose

    View full-size slide