mvm - it's all in the (implementation) details

80
Mobile Architecture From The Patterns To The Deployment

Upload: florina-muntenescu

Post on 11-Apr-2017

64 views

Category:

Software


1 download

TRANSCRIPT

Page 1: MVM - It's all in the (Implementation) Details

Mobile Architecture

From The Patterns To The Deployment

Page 2: MVM - It's all in the (Implementation) Details

MVVMIt’s All In The ImplementationDetails

Page 3: MVM - It's all in the (Implementation) Details

ModelViewViewModel

Page 4: MVM - It's all in the (Implementation) Details

DataModelView ViewModel1 … *

Page 5: MVM - It's all in the (Implementation) Details

Android Classes?Static Methods?

Page 6: MVM - It's all in the (Implementation) Details

Android Classes?Static Methods?

Providers

Page 7: MVM - It's all in the (Implementation) Details

context.getString(id);

Page 8: MVM - It's all in the (Implementation) Details

public class ResourceProvider {

Context context;

ResourceProvider(Context context){this.context = context;

}

}

Page 9: MVM - It's all in the (Implementation) Details

public class ResourceProvider {

Context context;

ResourceProvider(Context context){this.context = context;

}

}

String getString(@StringRes int id) { return }

context.getString(id);

Page 10: MVM - It's all in the (Implementation) Details

FirebaseRemoteConfig.getInstance() .getString(key);

Page 11: MVM - It's all in the (Implementation) Details

class RemoteConfigProvider { FirebaseRemoteConfig remoteConfig;

}

RemoteConfigProvider() { remoteConfig =

}

FirebaseRemoteConfig.getInstance()

Page 12: MVM - It's all in the (Implementation) Details

class RemoteConfigProvider { FirebaseRemoteConfig remoteConfig;

}

String getString(String key) { return remoteConfig.getString(key);}

RemoteConfigProvider() { remoteConfig =

}

FirebaseRemoteConfig.getInstance()

Page 13: MVM - It's all in the (Implementation) Details

DataModel

Page 14: MVM - It's all in the (Implementation) Details

View DataModelViewModel

Network

Database

SharedPreferences

Page 15: MVM - It's all in the (Implementation) Details

Articles

Page 16: MVM - It's all in the (Implementation) Details

Articles ArticlesDataModel

Page 17: MVM - It's all in the (Implementation) Details
Page 18: MVM - It's all in the (Implementation) Details

Category

Page 19: MVM - It's all in the (Implementation) Details

Category CategoriesDataModel

Page 20: MVM - It's all in the (Implementation) Details
Page 21: MVM - It's all in the (Implementation) Details

Articles

DataModel

Page 22: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Page 23: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

Page 24: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

Page 25: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews().flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

Page 26: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

.flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

.compose(new ArticleAgeFilterTransformer(filter))

Page 27: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

.flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

.compose(new ArticleAgeFilterTransformer(filter))

localDataSource

.getTopNews()

Page 28: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

.flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

.compose(new ArticleAgeFilterTransformer(filter))

localDataSource

.getTopNews()

Observable<List<Article>>

Page 29: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

.flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

.compose(new ArticleAgeFilterTransformer(filter))

.getTopNews()

Page 30: MVM - It's all in the (Implementation) Details

class ArticlesDataModel {

RemoteDataSource remoteDataSource; LocalDataSource localDataSource;

}

Observable<List<Article>> getOrfetchTopNewsArticles() {

}

return localDataSource.getTopNews()

.flatMap(articles -> articles.isEmpty()? remoteDataSource.getTopNews(): Observable.just(articles));

.compose(new ArticleAgeFilterTransformer(filter))

getOrfetchTopNewsArticles

.getTopNews()

Page 31: MVM - It's all in the (Implementation) Details

HomeView

Page 32: MVM - It's all in the (Implementation) Details

Article Teaser View

Page 33: MVM - It's all in the (Implementation) Details

Article Teaser View

ArticleTeaserViewModel

Page 34: MVM - It's all in the (Implementation) Details

ArticlesDataModel

Article Teaser View

ArticleTeaserViewModel

Page 35: MVM - It's all in the (Implementation) Details

DatabaseArticles

DataModel

Article Teaser View

ArticleTeaserViewModel

Page 36: MVM - It's all in the (Implementation) Details

Database

New Article

ArticlesDataModel

Article Teaser View

ArticleTeaserViewModel

Page 37: MVM - It's all in the (Implementation) Details

Articles

DataModel

New Article

Database

Article Teaser View

ArticleTeaserViewModel

getOrfetchTopNewsArticles

Page 38: MVM - It's all in the (Implementation) Details

ArticleTeaserViewModel

New Article

DatabaseArticlesDataModel

Article Teaser View

getTopNewsArticle

Page 39: MVM - It's all in the (Implementation) Details

Article Teaser View

New Article

DatabaseArticlesDataModel

ArticleTeaserViewModel

Page 40: MVM - It's all in the (Implementation) Details

DataModel uses the Repository pattern

One DataModel per business model

DataModel drives the data flow

Page 41: MVM - It's all in the (Implementation) Details

ViewViewModel

Page 42: MVM - It's all in the (Implementation) Details

Article Teaser View

<LinearLayout>

<…ArticleTeaserView … />

</LinearLayout>

Page 43: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

ArticleTeaserView(Context context){...onInject();

}

}

Page 44: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

}

new ArticleTeaserViewModel()

ArticleTeaserView(Context context){...onInject();

}

Page 45: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

}

void onAttachedToWindow(){ bind();}

Page 46: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

}

void onAttachedToWindow(){ bind();}

void bind(){ subscription.add(

viewModel.getTopNewsArticle() .subscribeOn(…)

.observeOn(…) .subscribe(this::showArticle,

error -> Timber.e(error, “Error ...”);}

Page 47: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

}

void onDettachedFromWindow(){ subscription.clear();

}

Page 48: MVM - It's all in the (Implementation) Details

class ArticleTeaserView extends View{

}

void onDettachedFromWindow(){ subscription.clear();

} viewModel.dispose();

Page 49: MVM - It's all in the (Implementation) Details

Lifecycle of the ViewModel depends on the lifecycle of the View

Only the View has a reference to the corresponding ViewModel

View is declared in the XML

Only other native android classes know about the View

Page 50: MVM - It's all in the (Implementation) Details

Model-View-ViewModelLists

Page 51: MVM - It's all in the (Implementation) Details

TopNewsStream View

class TopNewsStreamViewModel {

}

Page 52: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

}

Observable<TopNewsPages> getTopNewsPages(){

… }

TopNewsStream View

Page 53: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

}

@AutoValueabstract class TopNewsPages {

List<Displayable> displayables();

int position();}

Observable<TopNewsPages> getTopNewsPages(){

… }

TopNewsStream View

Page 54: MVM - It's all in the (Implementation) Details

class TopNewsStreamView extends Fragment {

}

@InjectTopNewsStreamViewModel viewModel;

Page 55: MVM - It's all in the (Implementation) Details

void onResume(){ bind();}

void onPause(){ unbind();}

class TopNewsStreamView extends Fragment{

}

Page 56: MVM - It's all in the (Implementation) Details

class TopNewsStreamView extends Fragment{

}

void bind(){ subscription.add(

viewModel.getTopNewsPages() .subscribe(pages -> setupPages(pages))

}

Page 57: MVM - It's all in the (Implementation) Details

class TopNewsStreamView extends Fragment{

}

void bind(){ subscription.add(

viewModel.getTopNewsPages() .subscribe(pages -> setupPages(pages))

}

void setupPages(TopNewsPages pages){ // based on pages.displayables() // update RecyclerView.Adapter // using DiffUtil.calculateDiff

}

Page 58: MVM - It's all in the (Implementation) Details

void bind(){ subscription.add(

viewModel.getTopNewsPages() .subscribe(pages -> setupPages(pages))

}

void setupPages(TopNewsPages pages){ // based on pages.displayables() // update RecyclerView.Adapter // using DiffUtil.calculateDiff

}// based on pages.position()// update position

class TopNewsStreamView extends Fragment{

}

Page 59: MVM - It's all in the (Implementation) Details

class DisplayablesRecyclerViewAdapterextends RecyclerView.Adapter<BoundViewHolder> {

}

Page 60: MVM - It's all in the (Implementation) Details

class DisplayablesRecyclerViewAdapterextends RecyclerView.Adapter<BoundViewHolder> {

}

onCreateItemView(ViewGroup parent, int viewType){

// create View // create the ViewModel for the View

}

Page 61: MVM - It's all in the (Implementation) Details

Open Article

Page 62: MVM - It's all in the (Implementation) Details

Open Article

Share Article

Page 63: MVM - It's all in the (Implementation) Details

Open Article

Share Article

Label should disappear after 5sec

Page 64: MVM - It's all in the (Implementation) Details

class TopNewsArticleViewModel {

void openArticle(){…

}

void share(){…

}

Observable<Boolean> isNewLabelVisible(){…

}}

Page 65: MVM - It's all in the (Implementation) Details

ViewModel creates and emits the Model of the View

View subscribes to the emissions of the Model

View updates the RecyclerView.Adapter

In Adapter.onCreateItemView the RecylerView’s item and the corresponding ViewModel are created.

Page 66: MVM - It's all in the (Implementation) Details

Open Article

Page 67: MVM - It's all in the (Implementation) Details

no ViewModel

Open Article

Page 68: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

}

Page 69: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

@AutoValueabstract class Displayable (){

Article article();

}

}

Page 70: MVM - It's all in the (Implementation) Details

@AutoValueabstract class Displayable (){

Article article();

}

Action0 onClickAction();

}

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

Page 71: MVM - It's all in the (Implementation) Details

Displayable create(Article article, Action0 action){ …}

@AutoValueabstract class Displayable (){

Article article();

}

Action0 onClickAction();

}

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

Page 72: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

return dataModel.getTopNewsArticles() .flatMap(article ->

createDisplayable(article)) ... }

Page 73: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

return dataModel.getTopNewsArticles() .flatMap(article ->

createDisplayable(article)) ... }

Displayable createDisplayable(Article article){ return Displayable.create(article,

new Action0() { @Override public void call() { // handle item click }}

Page 74: MVM - It's all in the (Implementation) Details

class TopNewsStreamViewModel {

Observable<List<Displayable>> getDisplayables(){

}

return dataModel.getTopNewsArticles() .flatMap(article ->

createDisplayable(article)) ... }

Displayable createDisplayable(Article article){ return Displayable.create(article,

new Action0() { @Override public void call() { // handle item click }}

Page 75: MVM - It's all in the (Implementation) Details

class TopNewsViewHolder implements RecyclerView.ViewHolder {

}

Page 76: MVM - It's all in the (Implementation) Details

class TopNewsViewHolder implements RecyclerView.ViewHolder {

}

TextView title;…

Page 77: MVM - It's all in the (Implementation) Details

class TopNewsViewHolder implements RecyclerView.ViewHolder {

}

TextView title;…

void bindItem(Displayable displayable){title.setText(displayable.article().getTitle())

}

Page 78: MVM - It's all in the (Implementation) Details

class TopNewsViewHolder implements RecyclerView.ViewHolder {

}

TextView title;…

void bindItem(Displayable displayable){title.setText(displayable.article().getTitle())

}

view.setOnClickListener( v -> displayable.onClickAction().call())

Page 79: MVM - It's all in the (Implementation) Details

Define an Action in the View’s Model

Bind the Model to the View via the RecyclerView.ViewHolder

Trigger the Action

Action is handled by the ViewModel

Page 80: MVM - It's all in the (Implementation) Details

MVVMIt’s All In The ImplementationDetails