SlideShare una empresa de Scribd logo
UI Navigation
Mike Nakhimovich
Dispatching State
Mike Nakhimovich
Apps have a UI
Apps have a UI
Search View
Apps have a UI
Search View
ResultsView
Apps have a UI
Search View
ResultsView
ErrorView
Apps have a UI
Search View
ResultsView
ErrorView
LoadingView
Users interact with the UI
Pizza
Interactions lead to State change
Pizza
Pizza
Interactions lead to State change
PizzaPizza
State change need to be rendered
What is state?
A representation of UI
at a certain point in time
What is state?
State determines how the
UI renders & behaves
Android lacks patterns for
working with state & views
How to create state
How to pass state
How to hold state
How do we think about state?
data class ScreenState(
val searchResults:List<Results>,
val searchTerm:String,
val isLoading:Boolean)
Example: state modeled as a single data class
data class ScreenState(
val searchResults:List<Results>,
val searchTerm:String,
val isLoading:Boolean,
val CartItems:List<Items>,
val userId:Long
Example: state modeled as a single growing data class
data class ScreenState(
val searchResults:List<Results>,
val searchTerm:String,
val isLoading:Boolean,
val CartItems:List<Items>,
val userId:Long
State modeled as a God class
Android devs love being reactive,
why not represent state as a stream?
Lately, I’ve been using a
centralized dispatcher to model
state as a reactive stream
What’s a dispatcher?
A dispatcher is an object that receives
and sends messages about state
that the UI reacts to
A dispatcher is an object that receives
and sends messages about state
Why a state dispatcher?
Decouple producers of state
change from its consumers
Why a state dispatcher?
Journey to dispatcher
User types a search term
Pizza
User clicks search
Pizza
Loading should become visible
Pizza
Followed by results
Pizza
Pizza
Proposal 1: Encapsulate Screen
in a ScreenPresenter
How do we tell views what to display?
PizzaScreen Presenter
SearchView ResultsView
Pizza
Proposal 1: Encapsulate Screen
in a ScreenPresenter
How do we tell ResultsViews what to display?
Pizza
But then… Product adds another view
PizzaScreen Presenter
SearchView ResultsViewLoadingView
And then… Product adds 3 more views
Pizza
PizzaScreen Presenter
SearchView ResultsViewLoading
ProfileTab DrawerViewCartView
Proposal 1: Create a ScreenPresenter
which contains both Presenters
How do we tell ResultsView what to display?
Pizza
Not very scalable
How do we tell ResultsView what to display?
Pizza
Proposal 2: Create a Listener
Proposal 2: Create a Listener
Pizza
SearchViewResultsView
Listens To
Proposal 2: Create a Listener
SearchViewResultsView
Listens To
LoadingView
ListensTo
Listens
To
Proposal 2: Create a Listener
Listeners lead to circular dependencies
Last Proposal
Use a centralized dispatcher
for ALL state change
A Dispatcher is responsible for receiving
state changes and emitting them
Use a centralized dispatcher
for ALL state change
Why a state dispatcher?
Views become coupled to the dispatcher not each other
SearchViewResultsView LoadingView
Dispatcher
Reactive state
UI creates new state
Reactive state
UI reacts to new state
Reactive state
With no hard references between UI
elements
Reactive state
Push rather than pull
Implementing reactive state
Reactive state
Sealed class State{
data class ShowingLoading():State
data class ShowingResults(val results:List<String>):State
data class ShowingError(val error:Error):State
}
Represent your state as immutable value objects
Reactive state
Push new state through a reactive stream
Interface Dispatcher
fun dispatch(state: State)
}
interface RxState {
fun <T> ofType(clazz: Class<T>): Observable<T>
}
Sealed class State{
data class ShowingLoading():State
data class ShowingResults(val results:List<String>):State
data class ShowingError(val error:Error):State
}
Reactive state
Anytime UI needs to change, dispatch a new state
dispatcher.dispatch(State.ShowingResults(resultData)
dispatcher.dispatch(State.ShowingLoading()
dispatcher.dispatch(State.ShowingError(errors)
Reactive state
Anytime state changes, react to new state
rxState.ofType(State.Results)
.map{it.data}
.subscribe{ mvpView.updateUI(data) }
Rather than tightly coupling Search & Results
we decouple them with a dispatcher
Reactive state visualized
Dispatcher
Reactive state
ResultsPresenter Subscribes to ShowResults states change
Dispatcher
ResultsPresenter
Reactive state
LoadingPresenter Subscribes to ShowLoading states change
Dispatcher
ResultsPresenter
LoadingPresenter
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingLoading
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingLoading
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingLoading
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingLoading
LoadingPresenter
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingLoading
LoadingPresenter
Reactive state
Dispatcher
SearchPresenterSearchView
SearchTerm
Reactive state
Search Presenter calls dispatcher.dispatch(State.ShowingResults(resultData)
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingResults
Reactive state
Dispatcher needs to emit a new State to subscribers
Dispatcher
SearchPresenter
ResultsPresenter
SearchView
SearchTerm
ShowingResults
Reactive state
Dispatcher Emits new ShowingResults State to ResultsPresenter
Dispatcher
SearchPresenter
ResultsPresenter
SearchView
SearchTerm
ShowingResults
Reactive state
Dispatcher Emits new ShowingResults State to subscribers
Dispatcher
SearchPresenterSearchView
SearchTerm
ShowingResults
ResultsPresenter
Reactive state
Dispatcher Emits new ShowingResults State to subscribers
Dispatcher
SearchPresenter
ResultsPresenter
SearchView
SearchTerm
ResultsView
ShowingResults
Reactive state
Multiple Views can listen to same state change Dispatcher
SearchPresenterSearchView
SearchTerm
ResultsPresenterResultsView
LoadingPresenterLoadingView
Reactive state
Dispatcher
SearchPresenterSearchView
ShowingResults
LoadingPresenterLoadingView
ResultsPresenterResultsView
Reactive state
Dispatcher
SearchPresenterSearchView
ShowingResultsShowingResults
LoadingPresenterLoadingView
ResultsPresenterResultsView
Reactive state
Dispatcher
SearchPresenterSearchView
ShowingResults
ShowingResults
LoadingPresenterLoadingView
ResultsPresenterResultsView
Reactive state
Dispatcher
SearchPresenterSearchView
ShowingResults
ShowingResults
LoadingPresenterLoadingView
ResultsPresenterResultsView
Reactive state
Dispatcher
SearchPresenterSearchView
ShowResults
Hide View
LoadingPresenterLoadingView
ResultsPresenterResultsView
Interacting with a dispatcher
Pizza
override fun attachView(view: NearYouMVPView) {
rxState.ofType(State.Results)
.map{it.data}
.subscribe{ mvpView.updateUI(data) }
}
Presenter subscribes on attach
Another presenter dispatches state change
Pizza
fun searchFor(searchTerm:String){
store.getResults(searchTerm)
.subscribe{dispatcher.dispatch(State.Results(data=it.results)}
Dispatcher emits state change
Pizza
fun searchFor(searchTerm:String){
store.getResults(searchTerm)
.subscribe{dispatcher.dispatch(State.Results(data=it.results)}
override fun attachView(view: NearYouMVPView) {
rxState.ofType(State.Results)
.map{it.data}
.subscribe{ mvpView.updateUI(data) }
}
Consumers & Producers of state stay decoupled
Pizza
fun searchFor(searchTerm:String){
store.getResults(searchTerm)
.subscribe{dispatcher.dispatch(State.Results(data=it.results)}
override fun attachView(view: NearYouMVPView) {
rxState.ofType(State.Results)
.map{it.data}
.subscribe{ mvpView.updateUI(data) }
}
How does data flow?
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults1
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults1
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults1
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView ShowingResults1
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults2
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults2
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
ShowingResults2
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView ShowingResults2
Reactive state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenter
More state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenter
Add To Cart
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenter
Add To Cart
More state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenter
Add To Cart
More state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenter
Add To Cart
More state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenterCartView
Add To Cart
More state
Dispatcher
SearchPresenterSearchView
ResultsPresenterResultsView
CartPresenterCartView
Add To Cart
More state
Emitting data is nice…
How about showing/hiding views?
When user clicks on cart, we
should show the cart view
HomeScreen
SearchView ResultsViewCartView
How?
We can combine state changes
through composition
Showing states
sealed class State {
object Cart : State()
data class Showing(val state: State) : State()
}
Showing states
dispatcher.dispatch(State.Showing(Cart))
sealed class State {
object Cart : State()
data class Showing(val state: State) : State()
}
Showing states
rxState.showing(Cart::class.java))
.subscribe({
mvpView.showCart()
}))
interface RxState {
fun showingNot(clazz: Class<out Screen>): Observable<Showing>
fun showing(clazz: Class<out Screen>): Observable<Showing>
}
We can show/hide views based on showing states
rxState.showingNot(Cart::class.java))
.subscribe({
mvpView.hide()
}))
rxState.showing(Cart::class.java))
.subscribe({
mvpView.showCart()
}))
Dispatching showing cart
rxState.showingNot(Cart::class.java))
.subscribe({
mvpView.hide()
}))
dispatcher.dispatch(State.Showing(Cart)) rxState.showing(Cart::class.java))
.subscribe({
mvpView.showCart()
}))
Dispatching Showing Checkout
Checkout
rxState.showingNot(Cart::class.java))
.subscribe({
mvpView.hide()
}))
dispatcher.dispatch(State.Showing(Checkout)) rxState.showing(Cart::class.java))
.subscribe({
mvpView.showCart()
}))
Showing/hiding works well
when all views attached
Not very scalable in real apps
Showing/hiding works well
when all views attached
How do we deal with deep flows?
How do we deal with deep flows?
Treat screen creation/routing as a state change
Dispatching screens workflow
Checkout
CartPresenterCartView
Checkout
CartPresenterCartView
Go To Checkout
Checkout
Screen.Checkout
CartPresenterCartView
Checkout
Screen.Checkout
CartPresenterCartView
Checkout
ScreenCreator
CartPresenterCartView
Creating(Screen.Checkout)
Checkout
ScreenCreator
CartPresenterCartView
Creating(Screen.Checkout)
Hidden CheckoutVIew
CartPresenterCartView
Screen.Checkout
ScreenCreator
CheckoutPresenter
CheckoutView
Hidden CheckoutVIew
CartPresenterCartView
Showing(Screen.Checkout)
ScreenCreator
CheckoutPresenter
CheckoutView
Hidden CheckoutVIew
CartPresenterCartView
Showing(Screen.Checkout)
ScreenCreator
CheckoutPresenter
CheckoutView
Hidden CheckoutVIew
CartPresenterCartView
Showing(Screen.Checkout)
ScreenCreator
CheckoutPresenter
CheckoutView
CheckoutView
With Data
CartPresenterCartView
Showing(Screen.Checkout)
ScreenCreator
CheckoutPresenter
CheckoutView
View tells presenter to go to new screen
presenter.openCart()
Presenter dispatches new screen state
sealed class Screen : State() {
data class Checkout(val payload:String) : Screen()
}
dispatcher.dispatch(Screen.Checkout)
Dispatcher encapsulates in a creating state
dispatcher.dispatch(Creating(Screen.Checkout))
Screen creator creates view/presenter
rxState.creating()
.subscribe({
createScreen(it)
})
Dispatches a showing state
rxState.creating()
.subscribe({
createScreen(it)
dispatcher.dispatch(Showing(it.screen))
})
Dispatcher adds each showing event to a back stack
override fun dispatch(state: State) {
when (state) {
is Showing->{
backstack.push(state)
rxState.push(state)
}
else -> rxState.push(state)
}
}
Dispatcher adds each showing event to a back stack
override fun dispatch(state: State) {
when (state) {
is Showing->{
backstack.push(state)
rxState.push(state)
}
else -> rxState.push(state)
}
}
val backstack: Stack<Showing> = Stack()
Dispatcher pushes new state to subscribers
override fun dispatch(state: State) {
when (state) {
is Showing->{
backstack.push(state)
rxState.push(state)
}
else -> rxState.push(state)
}
}
Presenter reacts to the showing state
override fun attachView(mvpView: CheckoutMVPView) {
rxState.showing(Screen.Checkout::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { mvpView.show() }
Screens = States
sealed class Screen : State() {
object Search : Screen()
object Cart:Screen()
Data class Checkout(val items:List<Item>) : Screen()
data class Payment(val items:List<Item>) : Screen()
}
Routing becomes a state change
sealed class Screen : State() {
object Search : Screen()
object Cart:Screen()
Data class Checkout(val items:List<Item>) : Screen()
data class Payment(val items:List<Item>) : Screen()
}
fun goToSearch() {dispatcher.dispatch(Screen.Search)}
fun openCart() { dispatcher.dispatch(Screen.Cart) }
fun submitNames(firstName: String, lastName: String) {
userRepository.update(firstName, lastName)
.subscribe { dispatcher.dispatch(Screen.CheckoutPayment(cartItems)) }
}
Need to go back?
Dispatcher.goBack()
override fun onBackPressed() {
dispatcher.goBack()
}
interface Dispatcher {
fun dispatch(state: State)
fun goBack()
}
Dispatcher.goBack()
Dispatcher will pop current showing state and
dispatch previous one again
interface Dispatcher {
fun dispatch(state: State)
fun goBack()
}
override fun onBackPressed() {
dispatcher.goBack()
}
State Stack = Back Stack
override fun onBackPressed() {
dispatcher.goBack()
}
interface Dispatcher {
fun dispatch(state: State)
fun goBack()
}
Back Stack = State Stack
interface Dispatcher {
fun dispatch(state: State)
fun goBack()
}
override fun onBackPressed() {
dispatcher.goBack()
}
Routing becomes a state change
Every view interaction becomes a state change
Your UI becomes a representation
of dispatched state
Which is dispatched by your UI
TLDR: Your app becomes a cycle
TLDR: Your app becomes a cycle
User interacts with view
TLDR: Your app becomes a cycle
User interacts with view
View dispatches state change
TLDR: Your app becomes a cycle
User interacts with view
View dispatches state change
View reacts to state change
TLDR: Your app becomes a cycle
User interacts with view
View dispatches state change
View reacts to state change
User interacts with view
github.com/
digitalbuddha/Dispatcher
Big thank you to Efeturi
Money for the UI

Más contenido relacionado

Similar a Dispatching Reactive State

Clean VIP (Clean Swift) architecture
Clean VIP (Clean Swift) architectureClean VIP (Clean Swift) architecture
Clean VIP (Clean Swift) architecture
Jianbin LIN
 
ReSwift & Machine Learning
ReSwift & Machine LearningReSwift & Machine Learning
ReSwift & Machine Learning
Rodrigo Leite
 
SEMrush 2
SEMrush 2SEMrush 2
SEMrush 2
Maria Kuzmina
 
Ph d defense_Department of Information Technology, Uppsala University, Sweden
Ph d defense_Department of Information Technology, Uppsala University, SwedenPh d defense_Department of Information Technology, Uppsala University, Sweden
Ph d defense_Department of Information Technology, Uppsala University, Sweden
Sabesan Manivasakan
 
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
VMware Tanzu
 
Reduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android BetterReduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android Better
Christina Lee
 
Chapter 4: Financial Statement Analysis
Chapter 4: Financial Statement AnalysisChapter 4: Financial Statement Analysis
Chapter 4: Financial Statement Analysis
Nada G.Youssef
 
Everything to Know About React Re-Rendering: A Comprehensive Guide
Everything to Know About React Re-Rendering: A Comprehensive GuideEverything to Know About React Re-Rendering: A Comprehensive Guide
Everything to Know About React Re-Rendering: A Comprehensive Guide
BOSC Tech Labs
 
Financial Statement Analysis
Financial Statement AnalysisFinancial Statement Analysis
Financial Statement Analysis
Faisal Hayat
 
Making design decisions in React-based ClojureScript web applications
Making design decisions in React-based ClojureScript web applicationsMaking design decisions in React-based ClojureScript web applications
Making design decisions in React-based ClojureScript web applications
Falko Riemenschneider
 
Rpt ppt
Rpt pptRpt ppt
Rpt ppt
sindhu T
 
Oracle business rules
Oracle business rulesOracle business rules
Oracle business rules
xavier john
 
ReactJs
ReactJsReactJs
Windows Phone 7 Unleashed Session 2
Windows Phone 7 Unleashed Session 2Windows Phone 7 Unleashed Session 2
Windows Phone 7 Unleashed Session 2
Wes Yanaga
 
Week 8
Week 8Week 8
Week 8
A VD
 
Whitepaper: Measuring Engagement in Native Advertising
Whitepaper:  Measuring Engagement in Native AdvertisingWhitepaper:  Measuring Engagement in Native Advertising
Whitepaper: Measuring Engagement in Native Advertising
Missy Steiner
 
Intuit's - Investor Day 2014 Presentation
Intuit's - Investor Day 2014 PresentationIntuit's - Investor Day 2014 Presentation
Intuit's - Investor Day 2014 Presentation
investorsintuitinc
 
Introduction To ReqPro
Introduction To ReqProIntroduction To ReqPro
Introduction To ReqPro
Leslie Munday
 
Build Restful Service using ADFBC
Build Restful Service using ADFBCBuild Restful Service using ADFBC
Build Restful Service using ADFBC
shravan kumar chelika
 
Oracle OSB Tutorial 1
Oracle OSB Tutorial 1Oracle OSB Tutorial 1
Oracle OSB Tutorial 1
Rakesh Gujjarlapudi
 

Similar a Dispatching Reactive State (20)

Clean VIP (Clean Swift) architecture
Clean VIP (Clean Swift) architectureClean VIP (Clean Swift) architecture
Clean VIP (Clean Swift) architecture
 
ReSwift & Machine Learning
ReSwift & Machine LearningReSwift & Machine Learning
ReSwift & Machine Learning
 
SEMrush 2
SEMrush 2SEMrush 2
SEMrush 2
 
Ph d defense_Department of Information Technology, Uppsala University, Sweden
Ph d defense_Department of Information Technology, Uppsala University, SwedenPh d defense_Department of Information Technology, Uppsala University, Sweden
Ph d defense_Department of Information Technology, Uppsala University, Sweden
 
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
Four Steps Toward a Safer Continuous Delivery Practice (Hint: Add Monitoring)
 
Reduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android BetterReduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android Better
 
Chapter 4: Financial Statement Analysis
Chapter 4: Financial Statement AnalysisChapter 4: Financial Statement Analysis
Chapter 4: Financial Statement Analysis
 
Everything to Know About React Re-Rendering: A Comprehensive Guide
Everything to Know About React Re-Rendering: A Comprehensive GuideEverything to Know About React Re-Rendering: A Comprehensive Guide
Everything to Know About React Re-Rendering: A Comprehensive Guide
 
Financial Statement Analysis
Financial Statement AnalysisFinancial Statement Analysis
Financial Statement Analysis
 
Making design decisions in React-based ClojureScript web applications
Making design decisions in React-based ClojureScript web applicationsMaking design decisions in React-based ClojureScript web applications
Making design decisions in React-based ClojureScript web applications
 
Rpt ppt
Rpt pptRpt ppt
Rpt ppt
 
Oracle business rules
Oracle business rulesOracle business rules
Oracle business rules
 
ReactJs
ReactJsReactJs
ReactJs
 
Windows Phone 7 Unleashed Session 2
Windows Phone 7 Unleashed Session 2Windows Phone 7 Unleashed Session 2
Windows Phone 7 Unleashed Session 2
 
Week 8
Week 8Week 8
Week 8
 
Whitepaper: Measuring Engagement in Native Advertising
Whitepaper:  Measuring Engagement in Native AdvertisingWhitepaper:  Measuring Engagement in Native Advertising
Whitepaper: Measuring Engagement in Native Advertising
 
Intuit's - Investor Day 2014 Presentation
Intuit's - Investor Day 2014 PresentationIntuit's - Investor Day 2014 Presentation
Intuit's - Investor Day 2014 Presentation
 
Introduction To ReqPro
Introduction To ReqProIntroduction To ReqPro
Introduction To ReqPro
 
Build Restful Service using ADFBC
Build Restful Service using ADFBCBuild Restful Service using ADFBC
Build Restful Service using ADFBC
 
Oracle OSB Tutorial 1
Oracle OSB Tutorial 1Oracle OSB Tutorial 1
Oracle OSB Tutorial 1
 

Más de Mike Nakhimovich

meetstore5.pdf
meetstore5.pdfmeetstore5.pdf
meetstore5.pdf
Mike Nakhimovich
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Mike Nakhimovich
 
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
Mike Nakhimovich
 
Open sourcing the store
Open sourcing the storeOpen sourcing the store
Open sourcing the store
Mike Nakhimovich
 
Advanced Dagger talk from 360andev
Advanced Dagger talk from 360andevAdvanced Dagger talk from 360andev
Advanced Dagger talk from 360andev
Mike Nakhimovich
 
Sword fighting with Dagger GDG-NYC Jan 2016
 Sword fighting with Dagger GDG-NYC Jan 2016 Sword fighting with Dagger GDG-NYC Jan 2016
Sword fighting with Dagger GDG-NYC Jan 2016
Mike Nakhimovich
 
Intro to Functional Programming with RxJava
Intro to Functional Programming with RxJavaIntro to Functional Programming with RxJava
Intro to Functional Programming with RxJava
Mike Nakhimovich
 

Más de Mike Nakhimovich (7)

meetstore5.pdf
meetstore5.pdfmeetstore5.pdf
meetstore5.pdf
 
Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
 
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
Data Loading Made Easy with Mike Nakhimovich DroidCon Italy 2017
 
Open sourcing the store
Open sourcing the storeOpen sourcing the store
Open sourcing the store
 
Advanced Dagger talk from 360andev
Advanced Dagger talk from 360andevAdvanced Dagger talk from 360andev
Advanced Dagger talk from 360andev
 
Sword fighting with Dagger GDG-NYC Jan 2016
 Sword fighting with Dagger GDG-NYC Jan 2016 Sword fighting with Dagger GDG-NYC Jan 2016
Sword fighting with Dagger GDG-NYC Jan 2016
 
Intro to Functional Programming with RxJava
Intro to Functional Programming with RxJavaIntro to Functional Programming with RxJava
Intro to Functional Programming with RxJava
 

Último

Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Mobile app Development Services | Drona Infotech
Mobile app Development Services  | Drona InfotechMobile app Development Services  | Drona Infotech
Mobile app Development Services | Drona Infotech
Drona Infotech
 
zOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL DifferenceszOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL Differences
YousufSait3
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative AnalysisOdoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Envertis Software Solutions
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
TaghreedAltamimi
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
Requirement Traceability in Xen Functional Safety
Requirement Traceability in Xen Functional SafetyRequirement Traceability in Xen Functional Safety
Requirement Traceability in Xen Functional Safety
Ayan Halder
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
dakas1
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
VALiNTRY360
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
dakas1
 
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
ssuserad3af4
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
Sven Peters
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
Alina Yurenko
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 

Último (20)

Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Mobile app Development Services | Drona Infotech
Mobile app Development Services  | Drona InfotechMobile app Development Services  | Drona Infotech
Mobile app Development Services | Drona Infotech
 
zOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL DifferenceszOS Mainframe JES2-JES3 JCL-JECL Differences
zOS Mainframe JES2-JES3 JCL-JECL Differences
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative AnalysisOdoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
Odoo ERP Vs. Traditional ERP Systems – A Comparative Analysis
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
Requirement Traceability in Xen Functional Safety
Requirement Traceability in Xen Functional SafetyRequirement Traceability in Xen Functional Safety
Requirement Traceability in Xen Functional Safety
 
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
一比一原版(UMN毕业证)明尼苏达大学毕业证如何办理
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
 
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
316895207-SAP-Oil-and-Gas-Downstream-Training.pptx
 
Microservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we workMicroservice Teams - How the cloud changes the way we work
Microservice Teams - How the cloud changes the way we work
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 

Dispatching Reactive State