I'm refactoring an android component to be adopting MVP architectural pattern. The problem I faced is that I have a fragment nesting other fragments in it.
1- The parent fragment hides/shows one of the nested fragments based on some conditions.
2- The child fragment passes data to the parent fragment which is observing it as here inspired by callback mechanism between fragment and activity.
I've 2 questions:
1- If I consider the fragment as the view of MVP, should I use distinct presenters for the parent fragment & the child fragment (1-to-1 mapping between presenters & views) or only one presenter for both and why?
2- If I'm supposed to use distinct presenters, how should I handle passing data from the child fragment to the parent fragment as I barely know the Cons. and Pros. of:
Using an EventBus framework like Otto
Allow a presenter to have a direct reference on another presenter
Keep the communication in the view layer, away from the presenters as here, by having the nested view delegates calls it receives from its presenter to the parent view.
As with most architectur questions, I honestly think there is no right or wrong way. So please treat this just a suggestion (how I would implement this)
Each MVP unit should contain it's own presenter, which means there is one parent presenter (for the parent fragment) and several child presenters (one for each child fragment).
The child presenters all contain a parentPresenter field, which acts as a way to pass data / messages from the child to the parent. This parentPresenter is NOT the real presenter object, but an interface that includes only the needed calls.
If you need to pass data / messages the other way around (from the parent to the children), this is implemented via interface methodes in the view:
the parentPresenter calls its view
the parentView finds it's childFragment
the childFragment calls the appropriate interface call on the childPresenter
This way the whole communication is hidden behind clean interfaces and is also nicely testable. Hope this helps and let me know if you have any questions...
What I do in my application is using a callback mechanism between parent and child fragments for passing data between.
I also made a different presenters for each child fragment, because if one day I would like to use only one of the child fragments I would only override it's presenter methods.
Related
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).
I am working on an android application which has a recycler view with multiple view types. It was originally a MVP based app, which I am trying to convert to MVVM based architecture with LiveData and ViewModels. I have a home screen with a list of different types of views inside a recycler view. Every view has its own ViewModel and corresponding Model, resulting it with a home screen having recycler view as a collection of different view models.
This is my first implementation of LiveData, so facing some issues with design. I see some options here -
I create a parent HomeViewModel for my home activity which holds a LiveData object, consisting a list of different child ViewModels (representing different view types), making activity to its life cycle owner. Then I update each view(elements of recycler view) from one observer to that LiveData object.
I create individual LiveData objects for every child view/view models and make home activity as life cycle owner for each model/live data and update their views independently from activity with respective observers.
I create individual LiveData objects for every child view/view models and make respective view holder classes as their lifecycle owners and update individual views in respective holder classes.
Please help me suggesting the better way to deal with this or if there is any other approach other than the specified ones.
Thanks
I agreed to create a parent viewmodel such as "HomeViewModel", but I think the creation of viewmodel for each view type seems a little over-engineering, because every time you need to create a new view type, you need to create a new ViewModel, and I dont see any requirement for the view in recyclerview to have a dedicated viewmodel. In my perspective, the best approach is only have 1 viewmodel. Then I suggest you to implement adapter factory pattern for your recyclerview like in this article https://proandroiddev.com/writing-better-adapters-1b09758407d2 . If you have adapter factory pattern like that, you can generalize your recyclerview data, for example you can call it "Visitable" like the post above. Then, your viewmodel can hold just 1 livedata of visitable list, which observed by the fragment/activity.
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.
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
I have a created a Base Fragment. This Fragment contains 2 buttons on the right hand side.Now I want to created two more fragments which should be similar to the above base fragment but should have different control on the left hand side. For example FragmentA should have additional textView on left hand side. FragmentB should have textView and ImageButton on the left hand side. What is the good way to implement this ?
Should I add these control programmatically to the BaseFragment in onCreateView call of the extended FragmentA and FragmentB.
Or do I need to create different layout file for extended fragments which includes the base Fragment.In this case how would I inflate the base and extended fragment?
There're multiple ways to do that. So here're three of them I came up with:
Don't use inheritance. Instead add the reusable fragment as a nested fragment to FragmentA and FragmentB. With this approach it becomes a little difficult to send data to the nested fragment and listen to events from it.
Add an abstract method that inflates and configures an additional layout. Then subclass the fragment and override this method. This approach is pretty good if the inner layout is always positioned in the same way but may have different contents.
Add a layoutId parameter to the constructor of the base fragment class and pass if from subclasses. Override onViewCreated() in subclasses, call super implementation and perform subclass related configuration.