SlideShare a Scribd company logo
1 of 76
Download to read offline
Borrowing the best of the web
to make native better
Brandon Kase & Christina Lee
Why are we here?
Let me tell you a story!
about a button
a complicated button
Take 1:
boss asks for friend button
we say, 'OK! We'll do it this week!'
we do not finish it in a week
woah...this is very complicated!
boss is less than thrilled
Take 2:
boss asks for friend button
we say, 'OK! We'll do it this week!'
we modify our approach
we do not finish it in a week
we finish it in a day!
boss is thrilled
Brandon and Christina still have jobs, hurray!
What went wrong
Fetch data before view transitions
Optimistically update components
Send server requests and react to responses
Side Effects
Touch global state, make network requests
Side-effects are bad, but necessary
Most Common Pitfalls
Mutability
Asynchronicity
As developers, we are expected to handle
optimistic updates, server- side rendering,
fetching data before performing route
transitions, and so on... This complexity is
difficult to handle as we’re mixing two
concepts that are very hard for the human
mind to reason about: mutation and
asynchronicity. I call them Mentos and Coke”
Motivation | Redux
Luckily, we are not alone
Web Allies
The web faces all of these challenges and more
Unlike native; however, it's iteration rate is fast
Not "one" UI framework
So what did the web come up with?
Ways to manage side-effects
View
State
Ways to manage side-effects
Separation of concerns
Mutability and asynchronicity are decoupled
Flux
Redux
// The current application state (list of todos and chosen filter)
let previousState = {
visibleTodoFilter: 'SHOW_ALL',
todos: [ {
text: 'Read the docs.',
complete: false
} ]
}
// The action being performed (adding a todo)
let action = {
type: 'ADD_TODO',
text: 'Understand the flow.'
}
// Your reducer returns the next application state
let nextState = todoApp(previousState, action)
-- Dan Abaramov's Data Flow example in Redux
Cycle.js
Cycle.js
inputs = read effects you care about
outputs = write effects you want performed
all application logic is pure!
Cycle.js
from cycle.js.org
Common Traits
Unidirectional and circular data flows
Separation of concerns
How do we benefit on Android?
Logic is made easy
Implicit data flow of your app becomes explicit.
Immutable views of a mutable world
Debugging is made easy
All edge cases caught at compile-time.
Single source of truth.
Time Travel
How can you adopt this
View:
React native
Anvil
State:
Direct port of Redux/Cycle/etc.
We focused on State
Don't have to fight Android's UI framework
Easy to introduce
Native (kotlin)
Single-Atom-State (like redux)
Pure Functional Reactive (like cycle)
Composable (like cycle)
Aside: RxJava
Aside: RxJava
Reactive programming is programming with
asynchronous data streams
Andre Staltz
Global event emitter << Event buses << Data stream
Aside: RxJava
When we say streams, we mean push-based event streams,
not pull-based infinite list streams
Aside: RxJava
What can this look like in practice?
Streams of button taps
Streams of snapshots of changing data
Streams from network responses
Aside: RxJava
RxJava
Reactive programming with streams
Tools to combine and transform those streams
Aside: RxJava
from RxMarbles
Aside: RxJava
from RxMarbles
Aside: RxJava
Observable.just(1,2,3)
Example
Example
0:09 0:14
Not just a counter
1. View-Model State
data class /*View-Model*/ State(
val numLikes: Int,
val numComments: Int,
val showNewHighlight: Boolean,
val imgUrl: String?,
val showUndo: Boolean
)
2. View Intentions
// Mode is either tapped or untapped
data class ViewIntentions(
val photos: Observable<Photo>,
val modes: Observable<Mode.Sum>,
val globalReadTs: Observable<Long>
)
3. Model State
// Mode is either tapped or untapped
data class /*Model*/ State(
val photo: Photo?,
val isNew: Boolean,
val mode: Mode.Sum,
): RamState<...>
val initialState = State(
photo = null,
isNew = false,
mode = Mode.untapped
)
4. View Intentions => Model State Changes
State changes? We want functional code. We want
immutability.
Think of a state change as a function
func change(currentState: State) -> State /*
nextState */
4. View Intentions => Model State Changes
val model: (ViewIntentions) -> Observable<(State) -> State> =
{ intentions ->
val modeChanges: Observable<(State) -> State> =
intentions.modes.map{ /*...*/ }
val photoChanges: Observable<(State) -> State> =
intentions.photos.map{ /*...*/ }
val tsChanges: Observable<(State) -> State> =
intentions.globalReadTs.map{ /*...*/ }
Observable.merge(
modeChanges, photoChanges, tsChanges)
}
4. View Intentions => Model State Changes
val modeChanges: Observable<(State) -> State> =
intentions.modes.map{ mode ->
{ state: State -> State(state.photo, state.isNew, mode) }
}
5. Model State => View-Model State
val viewModel: (Observable<Model.State>)->Observable<ViewModel.State> =
{ stateStream ->
stateStream
.map{ state ->
val undoable = state.mode == Mode.tapped
val likes = state.photo?.like_details ?: emptyList()
val comments = state.photo?.comments ?: emptyList()
ViewModel.State(
numLikes = likes.sumBy { it.multiplier },
numComments = comments.count,
showNewHighlight = state.isNew,
imgUrl = /* ... */,
showUndo = /*...*/
)
}
}
6. View-Model => Mutate the View
class PhotoComponent(
viewIntentions: ViewIntentions,
view: PhotoCellView
): StartStopComponent by Component(
driver = /* ... */,
model = /* ... */
)
6. View-Model => Mutate the View
driver = ViewDriver<ViewIntentions, ViewModel.State>(
intention = viewIntentions,
onViewState = { old, state ->
if (old?.imgUrl != state.imgUrl) {
view.setImg(state.imgUrl)
}
/* ... */
}
),
6. View-Model => Mutate the View
model = ViewDriver.makeModel(
initialState = Model.initialState,
createState = Model.createState,
model = Model.model,
viewModel = ViewModel.viewModel
)
Stick it in a recycler-view, hook up the side-effects into view
intentions and you're done
ViewIntentions
The inputs to your component
The photo, the mode, the tap timestamp
Model
Transform the inputs into state changes
Change mode, change isNew, change photo
ViewModel
Transform model state to view-model state
Extract photo url, like counts, etc
Component
Apply mutations to your view based on your view-model
Use the View-Model to change the underlying Android
view
Under the hood
Enforce viewintentions/model/view-model structure
RxJava does heavy-lifting
and a magic scan
Under the hood
Implementation of Redux in one-line
modelStream.scan(initialState,
{ currentState, transform ->
transform(currentState)
})
Bonus
Cycle.js-like side-effect drivers
Configurable model state persistance within state
Auto-start and stop components onPause/onResume
Just like cycle
read effects are inputs
write effects are outputs
Effects are decoupled from business logic
What does it look like in production?
Results: The Good
It wouldn't compile
Results: The Good
When it did compile, it worked!
Results: The Good
Incredibly modular and composable
LEGO-like plug-and-play
Results: The Good
Easy to test (by hand + by unit test) & debug
REALLY EASY
Mocking inputs is trivial
UI component is defined ONLY by it's state
Results: The Good
Easy to maintain
Spec change?
(possibly) add an input stream
add another mapin the model
Results: The Bad
Ramp up necessary
Results: The Bad
Animations are hard
chase or interpolate underlying state?
probably additive animations (google it)
Results: The Bad?
Boiler plate
(screenshot of files)
Always the 4 pieces
cyklicrepo has counter example in one file
Results: The Surprising
It's actually not slow
No noticeable perf hit
Results: The Conclusion
Results: The Conclusion
We have more powerful tools now
(i.e. Kotlin + Functional programming)
Let's use them
Question everything
Cyklic
Github: bkase/cyklic
Thanks
Brandon Kase Christina Lee
bkase@highlig.ht christina@highlig.ht
@bkase_ @runchristinarun
bkase.com
Github: bkase/cyklic

More Related Content

Similar to Reduxing UI: Borrowing the Best of Web to Make Android Better

[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation洪 鹏发
 
Architecting single-page front-end apps
Architecting single-page front-end appsArchitecting single-page front-end apps
Architecting single-page front-end appsZohar Arad
 
Android architecture components - how they fit in good old architectural patt...
Android architecture components - how they fit in good old architectural patt...Android architecture components - how they fit in good old architectural patt...
Android architecture components - how they fit in good old architectural patt...DroidConTLV
 
[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux ArchitectureNaukri.com
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with ReduxVedran Blaženka
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and SymfonyIgnacio Martín
 
React JS Interview Question & Answer
React JS Interview Question & AnswerReact JS Interview Question & Answer
React JS Interview Question & AnswerMildain Solutions
 
Getting Reactive with CycleJS and XStream
Getting Reactive with CycleJS and XStream Getting Reactive with CycleJS and XStream
Getting Reactive with CycleJS and XStream TechExeter
 
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay PlatonovSenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay PlatonovSencha
 
2018 02-22 React, Redux & Building Applications that Scale | React
2018 02-22 React, Redux & Building Applications that Scale | React2018 02-22 React, Redux & Building Applications that Scale | React
2018 02-22 React, Redux & Building Applications that Scale | ReactCodifly
 
iOS Architectures
iOS ArchitecturesiOS Architectures
iOS ArchitecturesHung Hoang
 
Unidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftUnidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftSeyhun AKYUREK
 
Content-Driven Apps with React
Content-Driven Apps with ReactContent-Driven Apps with React
Content-Driven Apps with ReactNetcetera
 
React JS: A Secret Preview
React JS: A Secret PreviewReact JS: A Secret Preview
React JS: A Secret Previewvaluebound
 

Similar to Reduxing UI: Borrowing the Best of Web to Make Android Better (20)

[Final] ReactJS presentation
[Final] ReactJS presentation[Final] ReactJS presentation
[Final] ReactJS presentation
 
Architecting single-page front-end apps
Architecting single-page front-end appsArchitecting single-page front-end apps
Architecting single-page front-end apps
 
Android architecture components - how they fit in good old architectural patt...
Android architecture components - how they fit in good old architectural patt...Android architecture components - how they fit in good old architectural patt...
Android architecture components - how they fit in good old architectural patt...
 
[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture
 
React state managmenet with Redux
React state managmenet with ReduxReact state managmenet with Redux
React state managmenet with Redux
 
React
ReactReact
React
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
React JS Interview Question & Answer
React JS Interview Question & AnswerReact JS Interview Question & Answer
React JS Interview Question & Answer
 
react redux.pdf
react redux.pdfreact redux.pdf
react redux.pdf
 
Reducers+flux=redux
Reducers+flux=reduxReducers+flux=redux
Reducers+flux=redux
 
Getting Reactive with CycleJS and XStream
Getting Reactive with CycleJS and XStream Getting Reactive with CycleJS and XStream
Getting Reactive with CycleJS and XStream
 
MVC 2.0 - A Breakthrough
MVC 2.0 - A BreakthroughMVC 2.0 - A Breakthrough
MVC 2.0 - A Breakthrough
 
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay PlatonovSenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
SenchaCon 2016: Handling Undo-Redo in Sencha Applications - Nickolay Platonov
 
2018 02-22 React, Redux & Building Applications that Scale | React
2018 02-22 React, Redux & Building Applications that Scale | React2018 02-22 React, Redux & Building Applications that Scale | React
2018 02-22 React, Redux & Building Applications that Scale | React
 
iOS Architectures
iOS ArchitecturesiOS Architectures
iOS Architectures
 
Reactjs
Reactjs Reactjs
Reactjs
 
Unidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftUnidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in Swift
 
Content-Driven Apps with React
Content-Driven Apps with ReactContent-Driven Apps with React
Content-Driven Apps with React
 
React JS: A Secret Preview
React JS: A Secret PreviewReact JS: A Secret Preview
React JS: A Secret Preview
 

Recently uploaded

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxnull - The Open Security Community
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 

Recently uploaded (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptxMaking_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
Making_way_through_DLL_hollowing_inspite_of_CFG_by_Debjeet Banerjee.pptx
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 

Reduxing UI: Borrowing the Best of Web to Make Android Better

  • 1. Borrowing the best of the web to make native better Brandon Kase & Christina Lee
  • 2. Why are we here? Let me tell you a story! about a button a complicated button
  • 3. Take 1: boss asks for friend button we say, 'OK! We'll do it this week!' we do not finish it in a week woah...this is very complicated! boss is less than thrilled
  • 4. Take 2: boss asks for friend button we say, 'OK! We'll do it this week!' we modify our approach we do not finish it in a week we finish it in a day! boss is thrilled Brandon and Christina still have jobs, hurray!
  • 5. What went wrong Fetch data before view transitions Optimistically update components Send server requests and react to responses
  • 6. Side Effects Touch global state, make network requests Side-effects are bad, but necessary
  • 8. As developers, we are expected to handle optimistic updates, server- side rendering, fetching data before performing route transitions, and so on... This complexity is difficult to handle as we’re mixing two concepts that are very hard for the human mind to reason about: mutation and asynchronicity. I call them Mentos and Coke” Motivation | Redux
  • 9.
  • 10. Luckily, we are not alone
  • 11. Web Allies The web faces all of these challenges and more Unlike native; however, it's iteration rate is fast Not "one" UI framework
  • 12. So what did the web come up with?
  • 13. Ways to manage side-effects View State
  • 14. Ways to manage side-effects Separation of concerns Mutability and asynchronicity are decoupled
  • 15.
  • 16. Flux
  • 17. Redux // The current application state (list of todos and chosen filter) let previousState = { visibleTodoFilter: 'SHOW_ALL', todos: [ { text: 'Read the docs.', complete: false } ] } // The action being performed (adding a todo) let action = { type: 'ADD_TODO', text: 'Understand the flow.' } // Your reducer returns the next application state let nextState = todoApp(previousState, action) -- Dan Abaramov's Data Flow example in Redux
  • 19. Cycle.js inputs = read effects you care about outputs = write effects you want performed all application logic is pure!
  • 22. Common Traits Unidirectional and circular data flows Separation of concerns
  • 23. How do we benefit on Android?
  • 24. Logic is made easy Implicit data flow of your app becomes explicit. Immutable views of a mutable world Debugging is made easy All edge cases caught at compile-time. Single source of truth. Time Travel
  • 25. How can you adopt this View: React native Anvil State: Direct port of Redux/Cycle/etc.
  • 26. We focused on State Don't have to fight Android's UI framework Easy to introduce
  • 27.
  • 28. Native (kotlin) Single-Atom-State (like redux) Pure Functional Reactive (like cycle) Composable (like cycle)
  • 30. Aside: RxJava Reactive programming is programming with asynchronous data streams Andre Staltz Global event emitter << Event buses << Data stream
  • 31. Aside: RxJava When we say streams, we mean push-based event streams, not pull-based infinite list streams
  • 32. Aside: RxJava What can this look like in practice? Streams of button taps Streams of snapshots of changing data Streams from network responses
  • 33. Aside: RxJava RxJava Reactive programming with streams Tools to combine and transform those streams
  • 39. Not just a counter
  • 40.
  • 41. 1. View-Model State data class /*View-Model*/ State( val numLikes: Int, val numComments: Int, val showNewHighlight: Boolean, val imgUrl: String?, val showUndo: Boolean )
  • 42.
  • 43. 2. View Intentions // Mode is either tapped or untapped data class ViewIntentions( val photos: Observable<Photo>, val modes: Observable<Mode.Sum>, val globalReadTs: Observable<Long> )
  • 44.
  • 45. 3. Model State // Mode is either tapped or untapped data class /*Model*/ State( val photo: Photo?, val isNew: Boolean, val mode: Mode.Sum, ): RamState<...> val initialState = State( photo = null, isNew = false, mode = Mode.untapped )
  • 46. 4. View Intentions => Model State Changes State changes? We want functional code. We want immutability. Think of a state change as a function func change(currentState: State) -> State /* nextState */
  • 47. 4. View Intentions => Model State Changes val model: (ViewIntentions) -> Observable<(State) -> State> = { intentions -> val modeChanges: Observable<(State) -> State> = intentions.modes.map{ /*...*/ } val photoChanges: Observable<(State) -> State> = intentions.photos.map{ /*...*/ } val tsChanges: Observable<(State) -> State> = intentions.globalReadTs.map{ /*...*/ } Observable.merge( modeChanges, photoChanges, tsChanges) }
  • 48. 4. View Intentions => Model State Changes val modeChanges: Observable<(State) -> State> = intentions.modes.map{ mode -> { state: State -> State(state.photo, state.isNew, mode) } }
  • 49.
  • 50. 5. Model State => View-Model State val viewModel: (Observable<Model.State>)->Observable<ViewModel.State> = { stateStream -> stateStream .map{ state -> val undoable = state.mode == Mode.tapped val likes = state.photo?.like_details ?: emptyList() val comments = state.photo?.comments ?: emptyList() ViewModel.State( numLikes = likes.sumBy { it.multiplier }, numComments = comments.count, showNewHighlight = state.isNew, imgUrl = /* ... */, showUndo = /*...*/ ) } }
  • 51.
  • 52. 6. View-Model => Mutate the View class PhotoComponent( viewIntentions: ViewIntentions, view: PhotoCellView ): StartStopComponent by Component( driver = /* ... */, model = /* ... */ )
  • 53. 6. View-Model => Mutate the View driver = ViewDriver<ViewIntentions, ViewModel.State>( intention = viewIntentions, onViewState = { old, state -> if (old?.imgUrl != state.imgUrl) { view.setImg(state.imgUrl) } /* ... */ } ),
  • 54. 6. View-Model => Mutate the View model = ViewDriver.makeModel( initialState = Model.initialState, createState = Model.createState, model = Model.model, viewModel = ViewModel.viewModel )
  • 55. Stick it in a recycler-view, hook up the side-effects into view intentions and you're done
  • 56.
  • 57. ViewIntentions The inputs to your component The photo, the mode, the tap timestamp Model Transform the inputs into state changes Change mode, change isNew, change photo ViewModel Transform model state to view-model state Extract photo url, like counts, etc Component Apply mutations to your view based on your view-model Use the View-Model to change the underlying Android view
  • 58. Under the hood Enforce viewintentions/model/view-model structure RxJava does heavy-lifting and a magic scan
  • 60. Implementation of Redux in one-line modelStream.scan(initialState, { currentState, transform -> transform(currentState) })
  • 61. Bonus Cycle.js-like side-effect drivers Configurable model state persistance within state Auto-start and stop components onPause/onResume
  • 62. Just like cycle read effects are inputs write effects are outputs Effects are decoupled from business logic
  • 63. What does it look like in production?
  • 64. Results: The Good It wouldn't compile
  • 65. Results: The Good When it did compile, it worked!
  • 66. Results: The Good Incredibly modular and composable LEGO-like plug-and-play
  • 67. Results: The Good Easy to test (by hand + by unit test) & debug REALLY EASY Mocking inputs is trivial UI component is defined ONLY by it's state
  • 68. Results: The Good Easy to maintain Spec change? (possibly) add an input stream add another mapin the model
  • 69. Results: The Bad Ramp up necessary
  • 70. Results: The Bad Animations are hard chase or interpolate underlying state? probably additive animations (google it)
  • 71. Results: The Bad? Boiler plate (screenshot of files) Always the 4 pieces cyklicrepo has counter example in one file
  • 72. Results: The Surprising It's actually not slow No noticeable perf hit
  • 74. Results: The Conclusion We have more powerful tools now (i.e. Kotlin + Functional programming) Let's use them Question everything
  • 76. Thanks Brandon Kase Christina Lee bkase@highlig.ht christina@highlig.ht @bkase_ @runchristinarun bkase.com Github: bkase/cyklic