MVM - It's all in the (Implementation) Details
-
Upload
florina-muntenescu -
Category
Software
-
view
64 -
download
1
Transcript of MVM - It's all in the (Implementation) Details
![Page 1: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/1.jpg)
Mobile Architecture
From The Patterns To The Deployment
![Page 2: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/2.jpg)
MVVMIt’s All In The ImplementationDetails
![Page 3: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/3.jpg)
ModelViewViewModel
![Page 4: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/4.jpg)
DataModelView ViewModel1 … *
![Page 5: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/5.jpg)
Android Classes?Static Methods?
![Page 6: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/6.jpg)
Android Classes?Static Methods?
Providers
![Page 7: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/7.jpg)
context.getString(id);
![Page 8: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/8.jpg)
public class ResourceProvider {
Context context;
ResourceProvider(Context context){this.context = context;
}
}
![Page 9: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/9.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/10.jpg)
FirebaseRemoteConfig.getInstance() .getString(key);
![Page 11: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/11.jpg)
class RemoteConfigProvider { FirebaseRemoteConfig remoteConfig;
}
RemoteConfigProvider() { remoteConfig =
}
FirebaseRemoteConfig.getInstance()
![Page 12: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/12.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/13.jpg)
DataModel
![Page 14: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/14.jpg)
View DataModelViewModel
Network
Database
SharedPreferences
![Page 15: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/15.jpg)
Articles
![Page 16: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/16.jpg)
Articles ArticlesDataModel
![Page 17: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/17.jpg)
![Page 18: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/18.jpg)
Category
![Page 19: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/19.jpg)
Category CategoriesDataModel
![Page 20: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/20.jpg)
![Page 21: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/21.jpg)
Articles
DataModel
![Page 22: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/22.jpg)
class ArticlesDataModel {
RemoteDataSource remoteDataSource; LocalDataSource localDataSource;
}
![Page 23: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/23.jpg)
class ArticlesDataModel {
RemoteDataSource remoteDataSource; LocalDataSource localDataSource;
}
Observable<List<Article>> getOrfetchTopNewsArticles() {
}
![Page 24: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/24.jpg)
class ArticlesDataModel {
RemoteDataSource remoteDataSource; LocalDataSource localDataSource;
}
Observable<List<Article>> getOrfetchTopNewsArticles() {
}
return localDataSource.getTopNews()
![Page 25: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/25.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/26.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/27.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/28.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/29.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/30.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/31.jpg)
HomeView
![Page 32: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/32.jpg)
Article Teaser View
![Page 33: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/33.jpg)
Article Teaser View
ArticleTeaserViewModel
![Page 34: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/34.jpg)
ArticlesDataModel
Article Teaser View
ArticleTeaserViewModel
![Page 35: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/35.jpg)
DatabaseArticles
DataModel
Article Teaser View
ArticleTeaserViewModel
![Page 36: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/36.jpg)
Database
New Article
ArticlesDataModel
Article Teaser View
ArticleTeaserViewModel
![Page 37: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/37.jpg)
Articles
DataModel
New Article
Database
Article Teaser View
ArticleTeaserViewModel
getOrfetchTopNewsArticles
![Page 38: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/38.jpg)
ArticleTeaserViewModel
New Article
DatabaseArticlesDataModel
Article Teaser View
getTopNewsArticle
![Page 39: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/39.jpg)
Article Teaser View
New Article
DatabaseArticlesDataModel
ArticleTeaserViewModel
![Page 40: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/40.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/41.jpg)
ViewViewModel
![Page 42: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/42.jpg)
Article Teaser View
<LinearLayout>
<…ArticleTeaserView … />
</LinearLayout>
![Page 43: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/43.jpg)
class ArticleTeaserView extends View{
ArticleTeaserView(Context context){...onInject();
}
}
![Page 44: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/44.jpg)
class ArticleTeaserView extends View{
}
new ArticleTeaserViewModel()
ArticleTeaserView(Context context){...onInject();
}
![Page 45: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/45.jpg)
class ArticleTeaserView extends View{
}
void onAttachedToWindow(){ bind();}
![Page 46: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/46.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/47.jpg)
class ArticleTeaserView extends View{
}
void onDettachedFromWindow(){ subscription.clear();
}
![Page 48: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/48.jpg)
class ArticleTeaserView extends View{
}
void onDettachedFromWindow(){ subscription.clear();
} viewModel.dispose();
![Page 49: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/49.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/50.jpg)
Model-View-ViewModelLists
![Page 51: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/51.jpg)
TopNewsStream View
class TopNewsStreamViewModel {
}
![Page 52: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/52.jpg)
class TopNewsStreamViewModel {
}
Observable<TopNewsPages> getTopNewsPages(){
… }
TopNewsStream View
![Page 53: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/53.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/54.jpg)
class TopNewsStreamView extends Fragment {
}
@InjectTopNewsStreamViewModel viewModel;
![Page 55: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/55.jpg)
void onResume(){ bind();}
void onPause(){ unbind();}
class TopNewsStreamView extends Fragment{
}
![Page 56: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/56.jpg)
class TopNewsStreamView extends Fragment{
}
void bind(){ subscription.add(
viewModel.getTopNewsPages() .subscribe(pages -> setupPages(pages))
}
![Page 57: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/57.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/58.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/59.jpg)
class DisplayablesRecyclerViewAdapterextends RecyclerView.Adapter<BoundViewHolder> {
}
![Page 60: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/60.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/61.jpg)
Open Article
![Page 62: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/62.jpg)
Open Article
Share Article
![Page 63: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/63.jpg)
Open Article
Share Article
Label should disappear after 5sec
![Page 64: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/64.jpg)
class TopNewsArticleViewModel {
void openArticle(){…
}
void share(){…
}
Observable<Boolean> isNewLabelVisible(){…
}}
![Page 65: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/65.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/66.jpg)
Open Article
![Page 67: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/67.jpg)
no ViewModel
Open Article
![Page 68: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/68.jpg)
class TopNewsStreamViewModel {
Observable<List<Displayable>> getDisplayables(){
}
}
![Page 69: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/69.jpg)
class TopNewsStreamViewModel {
Observable<List<Displayable>> getDisplayables(){
}
@AutoValueabstract class Displayable (){
Article article();
}
}
![Page 70: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/70.jpg)
@AutoValueabstract class Displayable (){
Article article();
}
Action0 onClickAction();
}
class TopNewsStreamViewModel {
Observable<List<Displayable>> getDisplayables(){
}
![Page 71: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/71.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/72.jpg)
class TopNewsStreamViewModel {
Observable<List<Displayable>> getDisplayables(){
}
return dataModel.getTopNewsArticles() .flatMap(article ->
createDisplayable(article)) ... }
![Page 73: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/73.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/74.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/75.jpg)
class TopNewsViewHolder implements RecyclerView.ViewHolder {
}
![Page 76: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/76.jpg)
class TopNewsViewHolder implements RecyclerView.ViewHolder {
}
TextView title;…
![Page 77: MVM - It's all in the (Implementation) Details](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/77.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/78.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/79.jpg)
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](https://reader036.fdocuments.in/reader036/viewer/2022062401/58e4ffe91a28abdf698b60d9/html5/thumbnails/80.jpg)
MVVMIt’s All In The ImplementationDetails