Does a BottomSheetFragment need ViewModel? - android

When working with Bottom Sheets and Dialog how to perform operation:
Use a SharedViewModel with fragment that created this bottom sheet?
Don't use a ViewModel at all?
Creating a separate ViewModel for the BottomSheet?
Any other approach that is best practice

If the bottom sheet/dialog is tightly bound to your "host" fragment (it shares some specific live data), and it is never going to be created from some other fragment, then it's OK to use a shared view model.
If the dialog is dead simple (like one input + 2 buttons), then the viewmodel might not be needed
If the dialog really needs a viewmodel (i.e. it fetches and displays some dynamic data), then a separate viewmodel makes sense

I'll go with the first approach by using a ShareViewModel, but if you understand the underlying layer, shared ViewModel is also ViewModel it's just a name convention we gave it to them.
Also sometimes it becomes tedious to write separate ViewModel to deal with fragments and bottom sheet where a MainActivity ViewModel can also do the exact same thing.
What I meant, in order to avoid complexity I use one view model per activity. Now, whenever I want to execute something in fragment or bottom sheet I just pass the view model in the constructor itself. Many people will think this is bad practice but it's not coz as per the concept of view model it will only be created and destroyed in accordance with the activity's lifecycle and only one instance will be created all along. Also by doing this, I can use Dependency injection with the fragment (I don't think that DI works with navigation component but I think you got my point).

Related

ViewModel with multiple fragments

I am just thinking about MVVM when it comes to bottom navigation view.
In this case it is one activity which has multiple fragments. If I use the ViewModel then the view model will hold the data for all fragments, right? Wouldn't this cause memory leaks or be bad for performance?
If I don't use the view model then I would be only holding one single Fragment data at a time.
Am I missing something?
There are multiple ways to implement this. Keep in mind, ViewModel doesn't have to be used only by Activity, it can be used by a Fragment or even a custom View.
In your case, if you have multiple fragments, you can create a ViewModel for each of them (if they are different off course).
The only thing that will kind of go out of MVVM pattern is the communication between fragment and activity.
If you still want to give the ViewModel the responsibility of telling the activity when to replace/remove/change a fragment, you can define an interface in each model (or a general interface) that will act as a callback, and you can set this callback on your ViewModel in onAttach or wherever fits for you.
Now your fragment, can pass the responsibility of notifying the activity to the ViewModel. I think this is one way of getting close to the MVVM patter in the case of Activity/Fragment communication, without to much trouble.

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...
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.
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).
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.

android MVP - can I have multiple presenters for custom views and fragments

So I have an a presenter that is already tied to an activity. The book says that one presenter should be tied to one view. But now I am adding a few fragments and lots of custom views. I am considering a fragment to be a view as well. The custom views will contain a little bit of logic in them. Both the fragments and custom views are contained in my activity of course.
My question is, should I re-use the same presenter in the fragment and custom views or should each view get its own presenter? I realize this is all opinion based but I want the best approach for testing and keeping code clean.
If i do have one presenter for all these fews then then interface the presenter uses will have many callback methods in it. Meanwhile if i did the opposite and created one presenter for each view it might be easier to read but how would i test it ?
View (Activity) can have multiple Presenters. In case of having multiple CustomViews for Activity, you can have one giant Presenter or Presenter per each CustomView. It depends on this:
If all CustomViews share same needs, one Presenter for all CustomViews is enough. Still two options for Presenter's scope:
Presenter has ActivityScope. Activity uses Presenter and gets called from Presenter. Then sends commands, data to CustomViews
Presenter has ViewScope. Each CustomView creates and destroys same Presenter
In case of CustomViews not sharing same needs, having one Presenter and ViewInterface, they will contain methods of all CustomViews needs, so each CustomView has to implement all declared methods in ViewInterface, leave some empty.
If CustomViews have different needs and method calls to Presenter, they should have their own Presenter.
If CustomViews have different needs and also some common needs, they share common need in one Presenter, specific needs in their own Presenters. Example for this: ActivityOne has CustomViewOne and CustomViewTwo. Common Presenter for both CustomViews can be FeedPresenter(considering both CustomViews have Feed List). Then CustomViewOne will have CustomPresenter1 and CustomViewTwo will have CustomPresenter2 for their specific needs.
Best practice is to create a basepresenter , then create presenter for each view implementing basepresenter

Android MVP for complex activity

I want to implement MVP pattern in my android project .
So , for Login-activity I did not have any problem .
But in Activity-Main I get confused a little and now i`m not sure how should I implement its Presenter !!!
In Activity-Main there are 3 sections as Navigation-Drawer , Toolbar and a fragment .
How can I make Presenter(s) now ? I doubt to create one presenter that implements 3 others implements or
directly create 3 presenter that have access to Activity-Main ?
Thanks
You can create refer to google's android-architecture .According to me you should create three different presenter for your each view and then bind them.you should check this part of sample,which has very basic design
What we did for a complex activity (30+ screens) was to divide each screen into View and Presenter components, where View battles with Android Views, and Presenter works out the logic (pulling and preparing data from controllers, network or local storage). But yeah, Google samples contain information about pretty much everything you'll need to start. Either way you should spend more time designing and thinking about the structure rather than actually implementing it. Good luck :)
From my understanding about MVP and its implementation is "P" is logic part which does all the logic/action handling. For this case i have personally created two presenters : Navigation Drawer/Home Presenter & Fragment Presenter.
Navigation/Home P : Only responsible to action related to Navigation and related to Main-Activity.
Fragement P : Having 1-1 relationship ie each fragment will have its own presenter.
For toolbar Presenter : I don't see much of a case where you should create separate presenter for toolbar, as all the action delegated via fragment and each fragment will have different items in toolbar and different handling as well.So collating them in one would just add complexity.

What is the role of the Activity class in MVC?

I know there have been quite a few questions about this, however, I'm still struggling to understand what role the Activity class should play when implementing the traditional Model-View-Controller design pattern on Android?
My gut feel is that it should be the Controller, however that means a one-to-one relationship between UI screens (since you must have one Activity per screen) and controllers, which defeats the point of MVC's loose coupling between the different components.
You are right. The xml interfaces could be defined as the View and your other class working with data as the Model.
The activity receive all the events and user inputs from the View ,so, we can easily said that it is the Controller.
But let's be clear , it's not a perfect (does it really exist ?) MVC
Have a look to this question , and more specifically , the first comment of the accepted answer, it may be useful
Activities can make competent controllers and, with fragments, you can also implement hierarchical MVC. Most of making MVC work is up to the programmer, because even in the strictest frameworks you can still find ways to do crazy things.
Android does not have a good architecture and it does not follow the MVC design pattern.
The best way to conceptualize Activity in MVC is as a View (with some controller logic) because it gets destroyed every time that a configuration change happens, such as a screen rotation or locale change, losing all its state.
The controller in this case would be the Application object, because it is your bridge to access the view (Activity and its GUI components) from code outside the Activity context. You have to use singletons so that there is only one Application object at a given time, otherwise there will be one Application object per process.
The Application object is not a good place to store the Model because its life cycle is detached from that of the Activities. It can get destroyed and recreated at any point of an Activity's life cycle (while the application is in the background) without causing it to restart, and then all its variables and references not assigned inside its onCreate() method will become null.
The Model therefore has to be stored on a GUI-less, headless fragment with setRetainInstance(true), that is linked to an activity, and has to be re-attached to it every time the activity is recreated. You have to use a fragment manager to ensure you are recovering the retained fragment and not creating it anew. This is also the best place to run background tasks, though you can also run them in the Application object. Never run tasks on an Activity as they will get destroyed on configuration changes.
I think the confusion may come in with defining a view as XML and so the Activity is mistaken for being the view. It's not. You pass the view (your XML layout) into the Activity which will then inflate the views contained within the XML layout. Your activity also passes data (models) into your views (EditText, TextView, extended version of base views, etc).
If you really want MVC then you can achieve this simply by setting up your view in an XML layout, create a view object which extends from your root view (if it's a RelativeLayout extend from that). From there you add your accessor methods and different logic needed for that view and you can then add unit testing around that.
In the Activity you will no longer pass in the ID of the layout and will instead do something like this:
CustomView customView = new CustomView(...);
setContentView(customView);
...
Of course almost all apps won't do this and you really don't need to do this. Calling findViewById is enough to link to that view object and call on the methods it has. Which in my mind, is MVC.

Categories

Resources