SlideShare a Scribd company logo
1 of 57
Download to read offline
www.softvision.com
MVVM with RxJava
Agenda
▪ MVP & MVVM
▪ Constructing a simple
Music App
▪ Intro Journey into RxJava
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
International Code of Signals
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
MVP
Presenter ModelView
User events
*Lifecycle Events
View updates Notifications
Updates/Requests
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
MVP
Presenter
<<interface>>
View
<<interface>>
MyPresenter MyModelMyView
User events
*Lifecycle Events
View updates Notifications
Updates/Requests
Model
<<interface>>
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
MVVM
ViewModel ModelView
Stream of data Notifications
Updates/Requests
Data bindings
Commands
Model
<<interface>>
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Data LayerBusiness Logic /
Domain Layer
Presentation Layer
Layered Architecture
Presenter /
ViewModel
View
Model
Use Case
Repository
DB
Rest API
Shared
Prefs
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Data LayerBusiness Logic /
Domain Layer
Presentation Layer
Layered Architecture
Presenter /
ViewModel
View
Model
Use Case
Repository
DB
Rest API
Shared
Prefs
Device Specific
(Location,
Notification)
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
What we want to do
Search on letter entered Loading Show results
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
What we want to do
Play Track Change icon when new track is playing
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
What we use
MVVM Architectural Pattern
RxJava
Retrofit
Realm
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
SearchViewModelSearchActivity
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
SearchViewModelSearchActivity
searchChangedAction
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - building blocks
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - building blocks
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - building blocks
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
public abstract class Subscriber<T> implements Observer<T>, Subscription {
…
}
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - building blocks
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
public abstract class Subscriber<T> implements Observer<T>, Subscription {
…
}
public class Observable<T> {
....
public final Subscription subscribe() {
Action1<T> onNext = Actions.empty();
Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED;
Action0 onCompleted = Actions.empty();
return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted));
}
}
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Observable & Subscriber
Observable<String> editTextObservable =
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Entered text");
subscriber.onCompleted();
}
});
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Observable & Subscriber
Observable<String> editTextObservable =
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Entered text");
subscriber.onCompleted();
}
});
private Subscriber<String> searchTriggered =
new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
};
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Observable & Subscriber
Observable<String> editTextObservable =
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Entered text");
subscriber.onCompleted();
}
});
private Subscriber<String> searchTriggered = new
Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
};
editTextObservable.subscribe(searchTriggered);
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Action
public interface Action1<T> extends Action {
void call(T t);
}
private Action1<String> searchTriggered = new Action1<String>() {
@Override
public void call(String searchedText) {
searchTracks(searchedText)
}
};
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
SearchViewModelSearchActivity
searchChangedAction
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Transform TextWatcher into an Observable
public static Observable<String> editTextObservable(EditText editText) {
return Observable. create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
TextWatcher textWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (subscriber .isUnsubscribed()) {
editText .removeTextChangedListener( this);
}
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (subscriber .isUnsubscribed()) {
editText .removeTextChangedListener( this);
}
subscriber .onNext(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
if (subscriber .isUnsubscribed()) {
editText .removeTextChangedListener( this);
}
}
};
editText .addTextChangedListener(textWatcher);
}
});
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchActivity (View)
private CompositeSubscription subscriptions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
subscriptions = new CompositeSubscription();
}
@Override
protected void onDestroy() {
super.onDestroy();
subscriptions.unsubscribe();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchActivity (View)
private CompositeSubscription subscriptions;
private SearchViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
subscriptions = new CompositeSubscription();
viewModel = new SearchViewModel();
}
@Override
protected void onDestroy() {
super.onDestroy();
subscriptions.unsubscribe();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchActivity (View)
private CompositeSubscription subscriptions;
private TracksViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
subscriptions = new CompositeSubscription();
viewModel = new TracksViewModel();
}
subscriptions.addAll(
CustomViewBindings.editTextObservable(searchEditText)
.subscribe(viewModel.searchChangedAction())
);
@Override
protected void onDestroy() {
super.onDestroy();
subscriptions.unsubscribe();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchViewModel (ViewModel)
private Action1<String> searchTriggered = new Action1<String>() {
@Override
public void call(String searchedText) {
searchTracks(searchedText)
.debounce(50, TimeUnit.MILLISECONDS)
.subscribe();
}
};
public Action1<String> searchChangedAction() {
return searchTriggered;
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Debounce
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Timeline
SearchActivity SearchViewModel TracksRepoUser
Open app
Subscribe for
TextWatcher events
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
SearchViewModelSearchActivity
searchChangedAction
isLoadingObservable
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchViewModel (ViewModel)
private BehaviorSubject<Boolean> isLoadingTracks = BehaviorSubject.create(false);
public Observable<Boolean> isLoadingObservable() {
return isLoadingTracks.asObservable();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchActivity (View)
subscriptions.addAll(
CustomViewBindings.editTextObservable(searchEditText)
.subscribe(viewModel.searchChangedAction()),
viewModel.isLoadingObservable()
.observeOn(AndroidSchedulers. mainThread())
.subscribe( new Action1<Boolean>() {
@Override
public void call(Boolean show) {
showLoading(show);
}
})
);
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Subject
A Subject is a bridge or proxy that acts both as an Observer and as an Observable.
public abstract class Subject<T, R> extends Observable<R> implements Observer<T>
Because it is an observer, it can subscribe to one or more Observables, and because it is an
Observable, it can pass through the items it observes by re-emitting them, and it can also emit
new items.
Types:
AsyncSubject
BehaviorSubject
PublishSubject
ReplaySubject
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - PublishSubject
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - BehaviorSubject
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Timeline
SearchActivity SearchViewModel TracksRepoUser
Subscribe for loading updates
Open app
Subscribe for
TextWatcher events
isLoadingObservable emits “false”
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Search Screen
SearchViewModelSearchActivity
searchChangedAction
isLoadingObservable
tracksObservable
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchViewModel (ViewModel)
private BehaviorSubject<List<TrackViewModel>> searchedTracks =
BehaviorSubject.create(new ArrayList<TrackViewModel>());
public Observable<List<TrackViewModel>> tracksObservable() {
return searchedTracks.asObservable();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchActivity (View)
subscriptions.addAll(
CustomViewBindings.editTextObservable(searchEditText).subscribe(viewModel.searchChangedAction()),
viewModel.isLoadingObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(show -> showLoading(show)),
viewModel.tracksObservable()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<TrackViewModel>>() {
@Override
public void call(List<TrackViewModel> newTracks) {
updateAdapter(newTracks);
}
})
);
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Timeline
SearchActivity SearchViewModel TracksRepoUser
Subscribe for loading updates
Open app
Subscribe for
TextWatcher events
Subscribe for track list updates
isLoadingObservable emits “false”
searchedTracksObservable emits
“empty array”
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
SearchViewModel (ViewModel)
private Observable<List<TrackViewModel>> searchTracks(String text) {
isLoadingTracks.onNext(true);
return TracksRepo.getInstance().searchTracks(text, searchedTracks.getValue().size())
.flatMap(new Func1<List<Track>, Observable<Track>>() {
@Override
public Observable<Track> call(List<Track> tracks) {
return Observable.from(tracks);
}
})
.map(new Func1<Track, TrackViewModel>() {
@Override
public TrackViewModel call(Track track) {
return getNewTrackViewModel(track);
}
})
.toList()
.doOnNext(tracks1 -> {
searchedTracks.onNext(tracks1);
}).onErrorResumeNext(throwable -> {
return Observable.empty();
}).doOnTerminate(() -> isLoadingTracks.onNext(false));
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Map
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - Map Example
.map(new Func1<Track, TrackViewModel>() {
@Override
public TrackViewModel call(Track track) {
return getNewTrackViewModel(track);
}
})
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - FlatMap
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
RxJava - FlatMap Example
.flatMap(new Func1<List<Track>, Observable<Track>>() {
@Override
public Observable<Track> call(List<Track> tracks) {
return Observable.from(tracks);
}
})
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Timeline
SearchActivity SearchViewModel TracksRepoUser
Subscribe for loading updates
Open app
Press “r”
Subscribe for
TextWatcher events
Subscribe for track list updates
Subscribe for searchTracks
Search tracks
Notify of Tracks Result
isLoadingObservable emits “true”
isLoadingObservable emits “false”
searchedTracksObservable emits
“empty array”
isLoadingObservable emits “false”
searchedTracksObservable emits
“List<TracksViewModel>”
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
List Item
TrackViewModelTrackView
isPlayingObservable
onPlayClicked
ViewModelView
Stream of data
Data bindings
Commands
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TrackViewModel
private BehaviorSubject<Boolean> isPlaying = BehaviorSubject.create(false);
public Observable<Boolean> isPlaying() {
return isPlaying.asObservable();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TrackView
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (this.viewModel != null) {
subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing));
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (subscription != null) {
subscription.unsubscribe();
}
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TrackView
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (this.viewModel != null) {
subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing));
}
}
public void bindViewModel(TrackViewModel viewModel) {
if (this.viewModel != null && subscription != null) {
subscription.unsubscribe();
}
this.viewModel = viewModel;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (subscription != null) {
subscription.unsubscribe();
}
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TrackViewModel
private BehaviorSubject<Boolean> isPlaying = BehaviorSubject.create(false);
private Action0 onPlayClicked;
public Observable<Boolean> isPlaying() {
return isPlaying.asObservable();
}
public void changePlayState() {
isPlaying.onNext(!isPlaying.getValue());
}
public void onPlayClicked() {
onPlayClicked.call();
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TrackView
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (this.viewModel != null) {
subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing));
}
}
public void bindViewModel(TrackViewModel viewModel) {
if (this.viewModel != null && subscription != null) {
subscription.unsubscribe();
}
this.viewModel = viewModel;
trackImage .setOnClickListener(v -> viewModel.onPlayClicked());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (subscription != null) {
subscription.unsubscribe();
}
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
TracksAdapter
private List<TrackViewModel> trackViewModels = new ArrayList<>();
@Override
public void onBindViewHolder(TracksViewHolder holder, int position) {
holder.bind(trackViewModels.get(position));
}
class TracksViewHolder extends RecyclerView.ViewHolder {
TrackView trackView;
private TracksViewHolder(View view) {
super(view);
trackView = (TrackView) view;
}
public void bind(TrackViewModel viewModel) {
trackView.bindViewModel(viewModel);
}
}
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
Timeline
TrackView TrackViewModelTracksAdapter
Subscribe for play state updates
isPlayingObservable emits “true or false”
isPlayingObservable emits “false or true”
TracksViewHolder
View Inflated
bindViewModel
attachedToWindow
user
play clicked
Unsubscribe from previous viewmodel
SearchViewModel
onPlayClicked action
changePlayState
dettachedFromWindow
user
Scroll item out of screen
Unsubscribe from viewmodel
ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA
What to explore next?
▪ Talk by Jacke Warthon ->
http://jakewharton.com/demystifying-rxjava-subscribers/
▪ RxBindings -> https://github.com/JakeWharton/RxBinding
▪ Android Data Binding Library ->
https://developer.android.com/topic/libraries/data-binding/index.ht
ml
▪ Debugging Rx -> Frodo -> https://github.com/android10/frodo
▪ Clean Architecture
▪ Books: Clean Code & Clean Coder - Robert C. Martin aka “Uncle Bob”
▪ Nice talk Simple made Esay:
https://www.infoq.com/presentations/Simple-Made-Easy
www.softvision.com
Questions?
Thank you!

More Related Content

Recently uploaded

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 

Recently uploaded (20)

Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

MVVM with RxJava Build Music App

  • 2. Agenda ▪ MVP & MVVM ▪ Constructing a simple Music App ▪ Intro Journey into RxJava
  • 3. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA International Code of Signals
  • 4. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA MVP Presenter ModelView User events *Lifecycle Events View updates Notifications Updates/Requests
  • 5. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA MVP Presenter <<interface>> View <<interface>> MyPresenter MyModelMyView User events *Lifecycle Events View updates Notifications Updates/Requests Model <<interface>>
  • 6. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA MVVM ViewModel ModelView Stream of data Notifications Updates/Requests Data bindings Commands Model <<interface>>
  • 7. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Data LayerBusiness Logic / Domain Layer Presentation Layer Layered Architecture Presenter / ViewModel View Model Use Case Repository DB Rest API Shared Prefs
  • 8. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Data LayerBusiness Logic / Domain Layer Presentation Layer Layered Architecture Presenter / ViewModel View Model Use Case Repository DB Rest API Shared Prefs Device Specific (Location, Notification)
  • 9. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA What we want to do Search on letter entered Loading Show results
  • 10. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA What we want to do Play Track Change icon when new track is playing
  • 11. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA What we use MVVM Architectural Pattern RxJava Retrofit Realm
  • 12. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen ViewModelView Stream of data Data bindings Commands
  • 13. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen SearchViewModelSearchActivity ViewModelView Stream of data Data bindings Commands
  • 14. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen SearchViewModelSearchActivity searchChangedAction ViewModelView Stream of data Data bindings Commands
  • 15. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - building blocks public interface Observer<T> { void onCompleted(); void onError(Throwable e); void onNext(T t); }
  • 16. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - building blocks public interface Observer<T> { void onCompleted(); void onError(Throwable e); void onNext(T t); } public interface Subscription { void unsubscribe(); boolean isUnsubscribed(); }
  • 17. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - building blocks public interface Observer<T> { void onCompleted(); void onError(Throwable e); void onNext(T t); } public abstract class Subscriber<T> implements Observer<T>, Subscription { … } public interface Subscription { void unsubscribe(); boolean isUnsubscribed(); }
  • 18. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - building blocks public interface Observer<T> { void onCompleted(); void onError(Throwable e); void onNext(T t); } public abstract class Subscriber<T> implements Observer<T>, Subscription { … } public class Observable<T> { .... public final Subscription subscribe() { Action1<T> onNext = Actions.empty(); Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED; Action0 onCompleted = Actions.empty(); return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted)); } } public interface Subscription { void unsubscribe(); boolean isUnsubscribed(); }
  • 19. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Observable & Subscriber Observable<String> editTextObservable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("Entered text"); subscriber.onCompleted(); } });
  • 20. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Observable & Subscriber Observable<String> editTextObservable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("Entered text"); subscriber.onCompleted(); } }); private Subscriber<String> searchTriggered = new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { } };
  • 21. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Observable & Subscriber Observable<String> editTextObservable = Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("Entered text"); subscriber.onCompleted(); } }); private Subscriber<String> searchTriggered = new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { } }; editTextObservable.subscribe(searchTriggered);
  • 22. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Action public interface Action1<T> extends Action { void call(T t); } private Action1<String> searchTriggered = new Action1<String>() { @Override public void call(String searchedText) { searchTracks(searchedText) } };
  • 23. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen SearchViewModelSearchActivity searchChangedAction ViewModelView Stream of data Data bindings Commands
  • 24. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Transform TextWatcher into an Observable public static Observable<String> editTextObservable(EditText editText) { return Observable. create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { TextWatcher textWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { if (subscriber .isUnsubscribed()) { editText .removeTextChangedListener( this); } } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (subscriber .isUnsubscribed()) { editText .removeTextChangedListener( this); } subscriber .onNext(s.toString()); } @Override public void afterTextChanged(Editable s) { if (subscriber .isUnsubscribed()) { editText .removeTextChangedListener( this); } } }; editText .addTextChangedListener(textWatcher); } }); }
  • 25. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchActivity (View) private CompositeSubscription subscriptions; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); subscriptions = new CompositeSubscription(); } @Override protected void onDestroy() { super.onDestroy(); subscriptions.unsubscribe(); }
  • 26. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchActivity (View) private CompositeSubscription subscriptions; private SearchViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); subscriptions = new CompositeSubscription(); viewModel = new SearchViewModel(); } @Override protected void onDestroy() { super.onDestroy(); subscriptions.unsubscribe(); }
  • 27. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchActivity (View) private CompositeSubscription subscriptions; private TracksViewModel viewModel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); subscriptions = new CompositeSubscription(); viewModel = new TracksViewModel(); } subscriptions.addAll( CustomViewBindings.editTextObservable(searchEditText) .subscribe(viewModel.searchChangedAction()) ); @Override protected void onDestroy() { super.onDestroy(); subscriptions.unsubscribe(); }
  • 28. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchViewModel (ViewModel) private Action1<String> searchTriggered = new Action1<String>() { @Override public void call(String searchedText) { searchTracks(searchedText) .debounce(50, TimeUnit.MILLISECONDS) .subscribe(); } }; public Action1<String> searchChangedAction() { return searchTriggered; }
  • 29. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Debounce
  • 30. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Timeline SearchActivity SearchViewModel TracksRepoUser Open app Subscribe for TextWatcher events
  • 31. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen SearchViewModelSearchActivity searchChangedAction isLoadingObservable ViewModelView Stream of data Data bindings Commands
  • 32. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchViewModel (ViewModel) private BehaviorSubject<Boolean> isLoadingTracks = BehaviorSubject.create(false); public Observable<Boolean> isLoadingObservable() { return isLoadingTracks.asObservable(); }
  • 33. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchActivity (View) subscriptions.addAll( CustomViewBindings.editTextObservable(searchEditText) .subscribe(viewModel.searchChangedAction()), viewModel.isLoadingObservable() .observeOn(AndroidSchedulers. mainThread()) .subscribe( new Action1<Boolean>() { @Override public void call(Boolean show) { showLoading(show); } }) );
  • 34. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Subject A Subject is a bridge or proxy that acts both as an Observer and as an Observable. public abstract class Subject<T, R> extends Observable<R> implements Observer<T> Because it is an observer, it can subscribe to one or more Observables, and because it is an Observable, it can pass through the items it observes by re-emitting them, and it can also emit new items. Types: AsyncSubject BehaviorSubject PublishSubject ReplaySubject
  • 35. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - PublishSubject
  • 36. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - BehaviorSubject
  • 37. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Timeline SearchActivity SearchViewModel TracksRepoUser Subscribe for loading updates Open app Subscribe for TextWatcher events isLoadingObservable emits “false”
  • 38. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Search Screen SearchViewModelSearchActivity searchChangedAction isLoadingObservable tracksObservable ViewModelView Stream of data Data bindings Commands
  • 39. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchViewModel (ViewModel) private BehaviorSubject<List<TrackViewModel>> searchedTracks = BehaviorSubject.create(new ArrayList<TrackViewModel>()); public Observable<List<TrackViewModel>> tracksObservable() { return searchedTracks.asObservable(); }
  • 40. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchActivity (View) subscriptions.addAll( CustomViewBindings.editTextObservable(searchEditText).subscribe(viewModel.searchChangedAction()), viewModel.isLoadingObservable() .observeOn(AndroidSchedulers.mainThread()) .subscribe(show -> showLoading(show)), viewModel.tracksObservable() .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<List<TrackViewModel>>() { @Override public void call(List<TrackViewModel> newTracks) { updateAdapter(newTracks); } }) );
  • 41. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Timeline SearchActivity SearchViewModel TracksRepoUser Subscribe for loading updates Open app Subscribe for TextWatcher events Subscribe for track list updates isLoadingObservable emits “false” searchedTracksObservable emits “empty array”
  • 42. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA SearchViewModel (ViewModel) private Observable<List<TrackViewModel>> searchTracks(String text) { isLoadingTracks.onNext(true); return TracksRepo.getInstance().searchTracks(text, searchedTracks.getValue().size()) .flatMap(new Func1<List<Track>, Observable<Track>>() { @Override public Observable<Track> call(List<Track> tracks) { return Observable.from(tracks); } }) .map(new Func1<Track, TrackViewModel>() { @Override public TrackViewModel call(Track track) { return getNewTrackViewModel(track); } }) .toList() .doOnNext(tracks1 -> { searchedTracks.onNext(tracks1); }).onErrorResumeNext(throwable -> { return Observable.empty(); }).doOnTerminate(() -> isLoadingTracks.onNext(false)); }
  • 43. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Map
  • 44. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - Map Example .map(new Func1<Track, TrackViewModel>() { @Override public TrackViewModel call(Track track) { return getNewTrackViewModel(track); } })
  • 45. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - FlatMap
  • 46. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA RxJava - FlatMap Example .flatMap(new Func1<List<Track>, Observable<Track>>() { @Override public Observable<Track> call(List<Track> tracks) { return Observable.from(tracks); } })
  • 47. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Timeline SearchActivity SearchViewModel TracksRepoUser Subscribe for loading updates Open app Press “r” Subscribe for TextWatcher events Subscribe for track list updates Subscribe for searchTracks Search tracks Notify of Tracks Result isLoadingObservable emits “true” isLoadingObservable emits “false” searchedTracksObservable emits “empty array” isLoadingObservable emits “false” searchedTracksObservable emits “List<TracksViewModel>”
  • 48. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA List Item TrackViewModelTrackView isPlayingObservable onPlayClicked ViewModelView Stream of data Data bindings Commands
  • 49. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TrackViewModel private BehaviorSubject<Boolean> isPlaying = BehaviorSubject.create(false); public Observable<Boolean> isPlaying() { return isPlaying.asObservable(); }
  • 50. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TrackView @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (this.viewModel != null) { subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing)); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (subscription != null) { subscription.unsubscribe(); } }
  • 51. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TrackView @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (this.viewModel != null) { subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing)); } } public void bindViewModel(TrackViewModel viewModel) { if (this.viewModel != null && subscription != null) { subscription.unsubscribe(); } this.viewModel = viewModel; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (subscription != null) { subscription.unsubscribe(); } }
  • 52. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TrackViewModel private BehaviorSubject<Boolean> isPlaying = BehaviorSubject.create(false); private Action0 onPlayClicked; public Observable<Boolean> isPlaying() { return isPlaying.asObservable(); } public void changePlayState() { isPlaying.onNext(!isPlaying.getValue()); } public void onPlayClicked() { onPlayClicked.call(); }
  • 53. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TrackView @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); if (this.viewModel != null) { subscription = this.viewModel.isPlaying().subscribe(playing -> setPlayIcon(playing)); } } public void bindViewModel(TrackViewModel viewModel) { if (this.viewModel != null && subscription != null) { subscription.unsubscribe(); } this.viewModel = viewModel; trackImage .setOnClickListener(v -> viewModel.onPlayClicked()); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (subscription != null) { subscription.unsubscribe(); } }
  • 54. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA TracksAdapter private List<TrackViewModel> trackViewModels = new ArrayList<>(); @Override public void onBindViewHolder(TracksViewHolder holder, int position) { holder.bind(trackViewModels.get(position)); } class TracksViewHolder extends RecyclerView.ViewHolder { TrackView trackView; private TracksViewHolder(View view) { super(view); trackView = (TrackView) view; } public void bind(TrackViewModel viewModel) { trackView.bindViewModel(viewModel); } }
  • 55. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA Timeline TrackView TrackViewModelTracksAdapter Subscribe for play state updates isPlayingObservable emits “true or false” isPlayingObservable emits “false or true” TracksViewHolder View Inflated bindViewModel attachedToWindow user play clicked Unsubscribe from previous viewmodel SearchViewModel onPlayClicked action changePlayState dettachedFromWindow user Scroll item out of screen Unsubscribe from viewmodel
  • 56. ATLANTA | AUSTIN | PHILADELPHIA | BENTONVILLE | ROMANIA | INDIA | AUSTRALIA | BRAZIL | NEPAL | CANADA What to explore next? ▪ Talk by Jacke Warthon -> http://jakewharton.com/demystifying-rxjava-subscribers/ ▪ RxBindings -> https://github.com/JakeWharton/RxBinding ▪ Android Data Binding Library -> https://developer.android.com/topic/libraries/data-binding/index.ht ml ▪ Debugging Rx -> Frodo -> https://github.com/android10/frodo ▪ Clean Architecture ▪ Books: Clean Code & Clean Coder - Robert C. Martin aka “Uncle Bob” ▪ Nice talk Simple made Esay: https://www.infoq.com/presentations/Simple-Made-Easy