SlideShare a Scribd company logo
Reactive UI in Android
Composing a new UI toolkit (pun intended)
Gil Goldzweig Goldbaum
@GilLongName GilGoldzweig GilGoldzweig
We have cookies!
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Reactive UI in Android
Composing a new UI toolkit (pun intended)
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
Jetpack Compose
Our current UI toolkit
Reactive UI in android - Gil Goldzweig Goldbaum, 10bis
AOSP View
TextView
Button
ViewGroup
FrameLayout LinearLayout EditText
Button
EditText
Layout XML
Using code
It wasn’t designed for it
android.view.View
android.view.ViewAndroid 1.6
TextViewButton extends
Spinner?
🤔
==
Spinner
Highest quality I found 😕
Android 0.8
Nov 5, 2007
android.view.ViewAndroid 4.2
Min SDK < 17 = No luck
😔
“API design is building future regret”
Chat haase
A fresh start
As part of JetPack family
Jetpack compose
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Declarative UI
● Take data as input
● Emits UI hierarchy when invoked
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Hello: Gil
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Hello: Rachel
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Hello: David
What is Compose?
Compiler plugin Runtime
Compiler plugin
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Composable functions are not
UI elements
Compiler plugin
@Composable
fun Greeting(name: String): Unit {
Text("Hello: $name")
}
What are composable functions?
Composable function
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Composable function
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Greeting
Composable function
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
}
Greeting
Text
Composable function
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
Text("Hello: $name")
}
Greeting
Text
Text
Composable function
Compiler plugin
@Composable
fun Greeting(name: String) {
Text("Hello: $name")
Text("Hello: $name")
}
Instructions tree
Greeting
Text
Text
Compose Runtime
Runtime
Takeaway
(10bis) mobile
app
Runtime
Takeaway
(10bis) mobile
app
Runtime
Compose
Jetnews app
Runtime
Compose
Jetnews app
Compose uses canvas under the
hood
AOSP View
TextView
Button
ViewGroup
FrameLayout EditTextLinearLayout
Button
EditText
Gradle dependency
Compose
Canvas
Surface Text VectorImage
@Composable
fun Button(text, onClick) {
}
Button
@Composable
fun Button(text, onClick) {
Surface(shape, color, border, elevation) {
}
}
Surface
Button
@Composable
fun Button(text, onClick) {
Surface(shape, color, border, elevation) {
Ripple(color = rippleColor) {
}
}
}
Surface
Ripple
Button
@Composable
fun Button(text, onClick) {
Surface(shape, color, border, elevation) {
Ripple(color = rippleColor) {
Clickable(onClick = onClick) {
}
}
}
}
Surface
Ripple
Clickable
Button
@Composable
fun Button(text, onClick) {
Surface(shape, color, border, elevation) {
Ripple(color = rippleColor) {
Clickable(onClick = onClick) {
Container(padding = paddings) {
}
}
}
}
}
Surface
Ripple
Clickable
Container
Button
@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
@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
@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
@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
fun Button
Reactive data flow
Reactive data flow
Data
Events
Spinner
Item Clicked
Selection
changed
We get
notified
Item Clicked
We get
notified
UI changes
Selection
updated
UI changes
Change
selection?
Current Compose
Reactive data flow
UIUpdate Data
Change UI
Reactive data flow
UIUpdate Data
✅
✅
Change data
Data changed,
Notifying UI
Reactive data flow
UIUpdate Data
Single source of truth
@Composable
fun Counter() {
}
Reactive data flow
@Composable
fun Counter() {
val count
}
Reactive data flow
@Composable
fun Counter() {
val count = 0
}
Reactive data flow
@Composable
fun Counter() {
val count = state { 0 }
}
Reactive data flow
@Composable
fun Counter() {
val count = state { 0 }
}
Reactive data flow
Should be treated
as an “observer”
@Composable
fun Counter() {
val count = state { 0 }
Column {
}
}
Reactive data flow
@Composable
fun Counter() {
val count = state { 0 }
Column {
Text("Counter demo")
}
}
Reactive data flow
@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
@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
@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
@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
@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
@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
@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
Jetpack compose
@Model
data class NewsModel(
var title: String,
var auther: String,
var imageUrl: String
)
@Model
@Model
data class NewsModel(
var title: String,
var auther: String,
var imageUrl: String
)
@Model
@Model
data class NewsModel(
var title: String,
var auther: String,
var imageUrl: String
)
data class NewsHolder(var news: List<NewsModel>)
@Model
@Model
data class NewsModel(
var title: String,
var auther: String,
var imageUrl: String
)
@Model
data class NewsHolder(var news: List<NewsModel>)
@Model
@Composable
fun NewsItem(model: NewsModel) {
}
@Model
@Composable
fun NewsItem(model: NewsModel) {
Row {
}
}
@Model
@Composable
fun NewsItem(model: NewsModel) {
Row {
Image(url = model.imageUrl)
}
}
@Model
@Composable
fun NewsItem(model: NewsModel) {
Row {
Image(url = model.imageUrl)
Column {
}
}
}
@Model
@Composable
fun NewsItem(model: NewsModel) {
Row {
Image(url = model.imageUrl)
Column {
Text(model.title)
}
}
}
@Model
@Composable
fun NewsItem(model: NewsModel) {
Row {
Image(url = model.imageUrl)
Column {
Text(model.title)
Text(model.auther, style = TextStyle(Color.Gray))
}
}
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
VerticalScroller {
}
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
VerticalScroller {
Column {
}
}
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
VerticalScroller {
Column {
holder.news.forEach { newsModel ->
}
}
}
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
VerticalScroller {
Column {
holder.news.forEach { newsModel ->
NewsItem(newsModel)
}
}
}
}
@Model
@Composable
fun NewsFeed(holder: NewsHolder) {
VerticalScroller {
Column {
holder.news.forEach { newsModel ->
NewsItem(newsModel)
Divider(height = 1.dp)
}
}
}
}
Jetpack compose
var newsHolder: NewsHolder
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
}
Jetpack compose
var newsHolder: NewsHolder
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
setContent {
}
}
Jetpack compose
var newsHolder: NewsHolder
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
setContent {
NewsFeed(newsHolder)
}
}
UI Repository
Presenter /
ViewModel
Jetpack compose
pullNews
newsPulled
fetchNews
onNewsFetched
override fun onNewsFetched(newsHolder: NewsHolder) {
}
Jetpack compose
override fun onNewsFetched(newsHolder: NewsHolder) {
this.newsHolder = newsHolder
}
Jetpack compose
override fun onUpdate() {
}
Jetpack compose
override fun onUpdate() {
newsHolder.news[0].title = "New title"
}
Jetpack compose
Compose can still work with the current
toolkit
@GenerateView
@Composable
fun NewsItem(model: NewsModel) {
...
}
@GenerateView
@Composable
@GenerateView
fun NewsItem(model: NewsModel) {
...
}
@GenerateView
Final notes
Compose is not
production ready!!!!!!!!!!
Available in Android
studio 4+
Compose’s slack
channel
Questions?
Thank you

More Related Content

What's hot (20)

PPT
J Query Public
pradeepsilamkoti
 
PDF
A proper introduction to Elm
Johannes Ridderstedt
 
PPT
Jquery 2
Manish Kumar Singh
 
PDF
Html css
John Felix
 
PDF
Introduzione JQuery
orestJump
 
PDF
CSS3 Refresher
Ivano Malavolta
 
PDF
Ruby sittin' on the Couch
langalex
 
PDF
HTML5 and CSS3 Refresher
Ivano Malavolta
 
PDF
HTML5 Canvas - The Future of Graphics on the Web
Robin Hawkes
 
PPTX
AngularJS
LearningTech
 
PPT
Jquery 3
Manish Kumar Singh
 
ODP
Drupal Best Practices
manugoel2003
 
PPTX
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
PDF
Coffeescript a z
Starbuildr
 
PDF
jQuery - Chapter 4 - DOM Handling
WebStackAcademy
 
PDF
JDD 2013 JavaFX
益裕 張
 
PPTX
Dartprogramming
Ali Parmaksiz
 
PDF
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
MongoDB
 
PPTX
jQuery, CSS3 and ColdFusion
Denard Springle IV
 
J Query Public
pradeepsilamkoti
 
A proper introduction to Elm
Johannes Ridderstedt
 
Html css
John Felix
 
Introduzione JQuery
orestJump
 
CSS3 Refresher
Ivano Malavolta
 
Ruby sittin' on the Couch
langalex
 
HTML5 and CSS3 Refresher
Ivano Malavolta
 
HTML5 Canvas - The Future of Graphics on the Web
Robin Hawkes
 
AngularJS
LearningTech
 
Drupal Best Practices
manugoel2003
 
jQuery Data Manipulate API - A source code dissecting journey
Huiyi Yan
 
Coffeescript a z
Starbuildr
 
jQuery - Chapter 4 - DOM Handling
WebStackAcademy
 
JDD 2013 JavaFX
益裕 張
 
Dartprogramming
Ali Parmaksiz
 
MongoDB .local Paris 2020: La puissance du Pipeline d'Agrégation de MongoDB
MongoDB
 
jQuery, CSS3 and ColdFusion
Denard Springle IV
 

Similar to Reactive UI in android - Gil Goldzweig Goldbaum, 10bis (20)

PDF
Declarative UIs with Jetpack Compose
Ramon Ribeiro Rabello
 
PPTX
Modern app development with Jetpack Compose.pptx
Md Shamsul Arafin Mahtab
 
PPTX
Compose Camp - Session3.pptx
GDSCAtharvaCollegeOf
 
PPTX
Compose in Theory
Garth Gilmour
 
PDF
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
DicodingEvent
 
PDF
Reactive clean architecture
Viktor Nyblom
 
PPTX
Compose Camp by GDSC NSUT
MOHITCHAURASIYA6
 
PDF
Functional Reactive Programming with Kotlin on Android - Giorgio Natili - Cod...
Codemotion
 
PPTX
Compose Camp Day 2.pptx
RajatKumarNayak5
 
PDF
Funtional Reactive Programming with Examples in Scala + GWT
Vasil Remeniuk
 
PDF
Mattia Manzati - Real-World MobX Project Architecture - Codemotion Rome 2019
Codemotion
 
PDF
Whatnot (Re)Compose
Whatnot3
 
PDF
Architectures in the compose world
Fabio Collini
 
PDF
Reduxing UI: Borrowing the Best of Web to Make Android Better
Christina Lee
 
PDF
Isomorphic Reactive Programming
Giorgio Natili
 
PPTX
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Codemotion
 
PDF
Compose Camp Day 3 PPT.pptx.pdf
METDSC
 
PDF
Reactive programming with RxJS - Taiwan
modernweb
 
PDF
Reactive programming on Android
Tomáš Kypta
 
PPTX
Reactive programming with rx java
CongTrung Vnit
 
Declarative UIs with Jetpack Compose
Ramon Ribeiro Rabello
 
Modern app development with Jetpack Compose.pptx
Md Shamsul Arafin Mahtab
 
Compose Camp - Session3.pptx
GDSCAtharvaCollegeOf
 
Compose in Theory
Garth Gilmour
 
Jetpack Compose untuk UI Masa Depan Bagian 2 - Sidiq Permana
DicodingEvent
 
Reactive clean architecture
Viktor Nyblom
 
Compose Camp by GDSC NSUT
MOHITCHAURASIYA6
 
Functional Reactive Programming with Kotlin on Android - Giorgio Natili - Cod...
Codemotion
 
Compose Camp Day 2.pptx
RajatKumarNayak5
 
Funtional Reactive Programming with Examples in Scala + GWT
Vasil Remeniuk
 
Mattia Manzati - Real-World MobX Project Architecture - Codemotion Rome 2019
Codemotion
 
Whatnot (Re)Compose
Whatnot3
 
Architectures in the compose world
Fabio Collini
 
Reduxing UI: Borrowing the Best of Web to Make Android Better
Christina Lee
 
Isomorphic Reactive Programming
Giorgio Natili
 
Samuele Resca - REACTIVE PROGRAMMING, DAMN. IT IS NOT ABOUT REACTJS - Codemot...
Codemotion
 
Compose Camp Day 3 PPT.pptx.pdf
METDSC
 
Reactive programming with RxJS - Taiwan
modernweb
 
Reactive programming on Android
Tomáš Kypta
 
Reactive programming with rx java
CongTrung Vnit
 
Ad

More from DroidConTLV (20)

PDF
Mobile Development in the Information Age - Yossi Elkrief, Nike
DroidConTLV
 
PDF
Doing work in the background - Darryn Campbell, Zebra Technologies
DroidConTLV
 
PDF
No more video loss - Alex Rivkin, Motorola Solutions
DroidConTLV
 
PDF
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
DroidConTLV
 
PDF
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
DroidConTLV
 
PDF
MVVM In real life - Lea Cohen Tannoudji, Lightricks
DroidConTLV
 
PDF
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
DroidConTLV
 
PDF
Building Apps with Flutter - Hillel Coren, Invoice Ninja
DroidConTLV
 
PDF
New Android Project: The Most Important Decisions - Vasiliy Zukanov
DroidConTLV
 
PDF
Designing a Design System - Shai Mishali, Gett
DroidConTLV
 
PDF
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
DroidConTLV
 
PDF
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
DroidConTLV
 
PDF
Flutter State Management - Moti Bartov, Tikal
DroidConTLV
 
PDF
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
DroidConTLV
 
PDF
DroidconTLV 2019
DroidConTLV
 
PDF
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
DroidConTLV
 
PDF
Introduction to React Native - Lev Vidrak, Wix
DroidConTLV
 
PDF
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
DroidConTLV
 
PDF
Educating your app – adding ML edge to your apps - Maoz Tamir
DroidConTLV
 
PDF
Constraint-ly motion - making your app dance - John Hoford, Google
DroidConTLV
 
Mobile Development in the Information Age - Yossi Elkrief, Nike
DroidConTLV
 
Doing work in the background - Darryn Campbell, Zebra Technologies
DroidConTLV
 
No more video loss - Alex Rivkin, Motorola Solutions
DroidConTLV
 
Mobile at Scale: from startup to a big company - Dor Samet, Booking.com
DroidConTLV
 
LiveData on Steroids - Giora Shevach + Shahar Ben Moshe, Climacell
DroidConTLV
 
MVVM In real life - Lea Cohen Tannoudji, Lightricks
DroidConTLV
 
Best Practices for Using Mobile SDKs - Lilach Wagner, SafeDK (AppLovin)
DroidConTLV
 
Building Apps with Flutter - Hillel Coren, Invoice Ninja
DroidConTLV
 
New Android Project: The Most Important Decisions - Vasiliy Zukanov
DroidConTLV
 
Designing a Design System - Shai Mishali, Gett
DroidConTLV
 
The Mighty Power of the Accessibility Service - Guy Griv, Pepper
DroidConTLV
 
Kotlin Multiplatform in Action - Alexandr Pogrebnyak - IceRockDev
DroidConTLV
 
Flutter State Management - Moti Bartov, Tikal
DroidConTLV
 
Fun with flutter animations - Divyanshu Bhargava, GoHighLevel
DroidConTLV
 
DroidconTLV 2019
DroidConTLV
 
Ok google, it's time to bot! - Hadar Franco, Albert + Stav Levi, Monday
DroidConTLV
 
Introduction to React Native - Lev Vidrak, Wix
DroidConTLV
 
Bang-Bang, you have been hacked - Yonatan Levin, KolGene
DroidConTLV
 
Educating your app – adding ML edge to your apps - Maoz Tamir
DroidConTLV
 
Constraint-ly motion - making your app dance - John Hoford, Google
DroidConTLV
 
Ad

Recently uploaded (20)

PDF
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
PDF
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
PDF
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
PDF
Simplify Your FME Flow Setup: Fault-Tolerant Deployment Made Easy with Packer...
Safe Software
 
PPTX
MARTSIA: A Tool for Confidential Data Exchange via Public Blockchain - Poster...
Michele Kryston
 
PDF
Pipeline Industry IoT - Real Time Data Monitoring
Safe Software
 
PDF
DoS Attack vs DDoS Attack_ The Silent Wars of the Internet.pdf
CyberPro Magazine
 
PDF
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
PDF
Bridging CAD, IBM TRIRIGA & GIS with FME: The Portland Public Schools Case
Safe Software
 
PDF
FME as an Orchestration Tool with Principles From Data Gravity
Safe Software
 
PDF
ICONIQ State of AI Report 2025 - The Builder's Playbook
Razin Mustafiz
 
PDF
Why aren't you using FME Flow's CPU Time?
Safe Software
 
PPSX
Usergroup - OutSystems Architecture.ppsx
Kurt Vandevelde
 
PDF
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
PDF
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
PDF
🚀 Let’s Build Our First Slack Workflow! 🔧.pdf
SanjeetMishra29
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
Bitkom eIDAS Summit | European Business Wallet: Use Cases, Macroeconomics, an...
Carsten Stoecker
 
PPTX
CapCut Pro PC Crack Latest Version Free Free
josanj305
 
PDF
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
“Scaling i.MX Applications Processors’ Native Edge AI with Discrete AI Accele...
Edge AI and Vision Alliance
 
Understanding The True Cost of DynamoDB Webinar
ScyllaDB
 
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
Simplify Your FME Flow Setup: Fault-Tolerant Deployment Made Easy with Packer...
Safe Software
 
MARTSIA: A Tool for Confidential Data Exchange via Public Blockchain - Poster...
Michele Kryston
 
Pipeline Industry IoT - Real Time Data Monitoring
Safe Software
 
DoS Attack vs DDoS Attack_ The Silent Wars of the Internet.pdf
CyberPro Magazine
 
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
Bridging CAD, IBM TRIRIGA & GIS with FME: The Portland Public Schools Case
Safe Software
 
FME as an Orchestration Tool with Principles From Data Gravity
Safe Software
 
ICONIQ State of AI Report 2025 - The Builder's Playbook
Razin Mustafiz
 
Why aren't you using FME Flow's CPU Time?
Safe Software
 
Usergroup - OutSystems Architecture.ppsx
Kurt Vandevelde
 
Proactive Server and System Monitoring with FME: Using HTTP and System Caller...
Safe Software
 
Supporting the NextGen 911 Digital Transformation with FME
Safe Software
 
🚀 Let’s Build Our First Slack Workflow! 🔧.pdf
SanjeetMishra29
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Bitkom eIDAS Summit | European Business Wallet: Use Cases, Macroeconomics, an...
Carsten Stoecker
 
CapCut Pro PC Crack Latest Version Free Free
josanj305
 
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 

Reactive UI in android - Gil Goldzweig Goldbaum, 10bis