20. Spinner: the weirdest case
public class MainActivity extends AppCompatActivity
implements Spinner.OnItemChangedListener {
What is the source of truth?
Who is the owner?
Who can change it?
onItemStateChanged() will be called after the event has happened
21. It turns out that android.widget
mixes state ownership and event
handling concepts
22. New UI toolkit goals
- Unbundled from platform releases (AndroidX)
- Fewer technology stack flowcharts (Custom View? Fragment?)
- Distinguish state ownership and event handling
- Write less code
23. What about building UI as simple as printing lines?
fun main(){
println("Hello Jetpack Compose")
}
25. What is Compose?
- Unbundled new set of UI widgets
- Inspired by React, Litho, Vue.js, Flutter
- A Kotlin compiler plugin
- Fully compatible with existing app code
- Experimental (0.1.0-dev02) - ** not ready for production yet **
27. UI as a function
@Composable
fun Hello(name: String){
Text(“Hello $name”)
}
Qualifier for Composables
Intercept and recompose the UI
tree
28. UI as a function (List of Composables)
@Composable
fun Trendings(newsList: List<News>){
for (news in newsList) {
NewsCard(news)
}
}
29. UI as a function (Dynamic composables)
@Composable
fun Trendings(news: List<News>){
if (news.isEmpty()) {
Text("You have no news today.")
} else {
NewsCard(news)
}
}
30. Composable building blocks
@Composable
fun Counter(model: CounterModel){
CounterTitle(model)
CounterContent(model)
CounterButtons(model)
}
@Composable
fun CounterHeader(model: CounterModel)
@Composable
fun CounterContent(model: CounterModel)
@Composable
fun CounterButtons(model: CounterModel)
31. Reactive UI upon model changes
@Composable
fun Counter(){
val model = CounterModel()
Column { Button(“Count”, onClick = { model.increment() }) }
Text(“Counter: ${model.value}”)
}
@Model
data class CounterModel(var value: Int = 0) {
fun increment() = value++
}
Indicates that composable updates
upon model changes
33. Top-down Data Flow
@Composable
fun Counter(model: CounterModel){
Column { Button(“Count”, onClick = { model.increment() }) }
Text(“Counter: ${model.value}”)
}
@Model
data class CounterModel(var value: Int = 0) {
fun increment() = value++
}
Data
34. Top-down Data Flow
@Composable
fun Counter(model: CounterModel){
Column { Button(“Count”, onClick = { model.increment() }) }
Text(“Counter: ${model.value}”)
}
@Model
data class CounterModel(var value: Int = 0) {
fun increment() = value++
}
Data
35. Top-down Data Flow
@Composable
fun Counter(model: CounterModel){
Column { Button(“Count”, onClick = { model.increment() }) }
Text(“Counter: ${model.value}”)
}
@Model
data class CounterModel(var value: Int = 0) {
fun increment() = value++
}
Data
36. Top-down Data Flow
@Composable
fun Counter(model: CounterModel){
Column { Button(“Count”, onClick = { model.increment() }) }
Text(“Counter: ${model.value}”)
}
@Model
data class CounterModel(var value: Int = 0) {
fun increment() = value++
}
Event
47. Learn more about Jetpack Compose
Jetpack Compose | Android Developers
Playing with Jetpack Compose dev preview
Diving into Jetpack Compose - Q42 Engineering - Medium
Declarative UI Patterns - Google I/O 2019
Android Jetpack Compose Review - Karumi Blog
https://www.github.com/ramonrabello/Compose-Counter