Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested MVP on Android: how to

I am working on an Android test project composed of 3 main parts, each of which developed following the MVP pattern. These parts are nested into each other and I would like to know if the strategy I am following is the correct/best one or not

Structure:

  • Book: ViewPager containing different Pages
  • Page: Custom LinearLayout containing multiple Items
  • Item: Custom View (in this example a simple button)

Each part uses a MVP structure (so for example for Book I made BookPresenter, BookView and BookModel, and the same for Page and Item)

As a user case I would like to keep track of how many times the user clicks the button and for each time change the Page background to a random color, and when the user reaches the 10th click tell the BookPresenter to go to the second page.

To do so I set up things so

  • BookView creates the BookPresenter, which in turns creates each PageView.
  • Each PageView creates the PagePresenter which in turns creates the ItemView (which ultimately creates the ItemPresenter)

In all this, the BookPresenter has a reference to the PagePresenter, and the PagePresenter has a reference to the ItemPresenter, so when some actions need to take place they can communicate to the child or the parent presenter in the structure

Now the question: Is this the right way to set up a system with nested MVPs? Because if I then want to have a PageView but instead of in a Book I need to put it in a Newspaper (other class with some alternative behaviour to Book) I still would need to recreate the whole chain of dependencies with Presenters and all the rest...

like image 730
kioli Avatar asked Mar 10 '23 03:03

kioli


1 Answers

How does a “Child-Presenter” communicate with its “Parent-Presenter”? They don't (directly, not via EventBus)

From my point of view such Parent-Child relations are code smells because they introduce a direct coupling between both Parent and Child, which leads to code that is hard to read, hard to maintain, where changing requirement affects a lot of components (hence it’s a virtually impossible task in large systems) and last but not least introduces shared state that is hard to predict and even harder to reproduce and debug.

So far so good, but somehow the information must flow from Presenter A to Presenter B: How does a Presenter communicate with another Presenter? They don’t! What would a Presenter have to tell another Presenter? Event X has happened? Presenters don’t have to talk to each other, they just observe the same Model (or the same part of the business logic to be precise). That’s how they get notified about changes: from the underlying layer.

Logic 1

Whenever an Event X happens (i.e. a user clicked on a button in View 1), the Presenter lets that information sink down to the business logic. Since the other Presenters are observing the same business logic, they get notified by the business logic that something has changed (model has been updated).

Logic 2

Source: http://hannesdorfmann.com/android/mosby3-mvi-4

So let's apply this on your example. You should have something like a Readable (if you want to make an abstraction over Book implements Readable and NewsPaper implements Readable). With Readable.getPageCount() you get the number of pages for ViewPager. With Readable.getCurrentPage() you get the current Page. Then you need some kind of Observer Pattern to be notified whenever the page is changed. You also need a Listener / Observer pattern when the user clicks on a button in ItemView. Such a click would be an Event X from the graphic above. On click on the button you let the information flow down through Presenter to your business logic which changes the Readable object. This change will then notify observers of this Readable object like PagePresenter that then updates the PageView to set the background color of the page.

So the key is: communicate via Business Logic, instead of some View to View or Presenter to Presenter communication.

Hope that helps.

like image 133
sockeqwe Avatar answered Mar 19 '23 04:03

sockeqwe