Architecture and RxJava

Post on 15-Apr-2017

1,185 views 0 download

transcript

Architecture with RxJava

Jolanda Verhoef

Blendle

Makes the world’s best

journalism available to

everyone, everywhere

@lojanda

Blendle

Makes the world’s best

journalism available to

everyone, everywhere

@lojanda

Architecture

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

@lojanda

Reactive Programming

@lojanda

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Standalone UI componentsOpening the Blendle Reader

@lojanda

Standalone UI componentsOpening the Blendle Reader

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

@lojanda

ArticlePreviewRepositorypublic Single<ArticlePreview> articlePreview$( String articleId ) { if ( cache.contains( articleId ) { return Single.just( cache.retrieve( articleId )); } else { return urlResolver.urlFor( articleId ) .flatMap( blendleApi::articlePreview$ ) .doOnSuccess( cache::store ); } }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

GetArticlePreviewUseCase

public Single<ArticlePreview> execute( String articleId ) { return articleRepository.articlePreview$( articleId ) .subscribeOn( Schedulers.io() ) .observeOn( AndroidSchedulers.mainThread() ); }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

ReaderPresenter

public void init( String articleId ) { getArticlePreviewUseCase.execute( articleId ) .subscribe( getView()::showArticlePreview, getView()::loadArticlePreviewFailed ); }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Standalone UI components++Inside the Blendle Reader

@lojanda

@lojanda

ReaderFragment

@lojanda

ReaderFragment

Toolbar

Featured Image

RecyclerView

@lojanda

ReaderFragment

Toolbar

Featured Image

RecyclerView

Publisher Logo

Bookmark Icon

Share Icon

Text Row

Image Row

……. Row

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

@lojanda

@lojanda

ArticleContextStore

private BehaviorSubject<String> subject;

public void changeArticleContext( final String newArticleId ) { subject.onNext( newArticleId ); }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

Reader@Override public View onCreateView( … ) { presenter.init( getArguments() != null ? getArguments().getInt( EXTRA_ARTICLE_ID ) : null ); }

@lojanda

public void init( @Nullable String articleId ) { if( articleId == null) articleId = articleContextStore.getArticleContext(); loadData( articleId ); }

VIE

WP

RE

SEN

TE

R

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Synchronising UI componentsBookmarking an article

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

BookmarkStoreprivate Map<String, BehaviorSubject<Boolean>> subjectMap;

public BehaviorSubject<Boolean> getBookmarked( String articleId ) { if( subjectMap.contains( articleId ) return subjectMap.get( articleId ); BehaviorSubject<Boolean> subject = BehaviorSubject.create(); subjectMap.put( articleId, subject ); return subject; }

public void setBookmarked( String articleId, Boolean bookmarked ) { getBookmarked().onNext( bookmarked ); }

@lojanda

BookmarkRepositorypublic Observable<Boolean> bookmarked$( String articleId ) { BehaviorSubject<Boolean> subject = bookmarkStore .getBookmarked( articleId );

if( ! subject.hasValue() ) { this.bookmarkedCall( articleId ) .subscribe( bookmarkStore::setBookmarked ); }

return subject; }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

GetBookmarkUseCase

public Observable<Boolean> execute( String articleId ) { return bookmarkRepository.bookmarked$( articleId ) .subscribeOn( Schedulers.io() ) .observeOn( AndroidSchedulers.mainThread() ); }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

BookmarkPresenter

public void init( String articleId ) { getBookmarkUseCase.execute( articleId ) .subscribe( getView()::showBookmarkValue ); }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Updating listsArticle reading list

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

@lojanda

@lojanda

Mutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

BookmarkStoreprivate PublishSubject<Pair<String, Boolean>> subject;

public Observable<Boolean> getBookmarkListener() { return subject; }

public void setBookmarked( String articleId, Boolean bookmarked ) { getBookmarked( articleId ).onNext( bookmarked ); subject.onNext( new Pair<>( articleId, bookmarked ); }

@lojanda

ReadingListPresenterpublic void init() { bookmarkStore.getBookmarkListener() .subscribe( this::bookmarkChanged ); }

public void bookmarkChanged( Pair<String, Boolean> pair ) { String articleId = pair.first; Boolean newBookmarkValue = pair.second; if( newBookmarkValue ) { getView().addBookmark( articleId ); } else { getView().removeBookmark( articleId ); } }

@lojandaMutable Data Stores

Context Stores

Mutable Data RepositoriesStatic Data

Repositories

Business Use Cases

Presenters

Custom Views Fragments Activities

Today’s subjects

Building standalone UI components

Building real standalone UI components

Synchronising UI components throughout the app

Updating lists after user interaction

@lojanda

Questions?Architecture https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html

Static datahttp://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/

Mutable data http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html

http://reactivex.io/RxJava/javadoc/rx/subjects/PublishSubject.html

https://lorentzos.com/rxjava-as-event-bus-the-right-way-10a36bdd49ba

@lojanda