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.
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'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.
The idea of using MVVM is that view observes ViewModelchanges and acts. I'm using an Activity which uses 7 Fragments and the navigation between them goes through observing individual changes in the Activity from different Fragments and launching/replacing Fragments accordingly. For instance,Fragment L calls setValue, then as a result the main Activity receives the event and switches to Fragment M and Fragment M calls getValue from the observed MutableLiveData and not directly functioning as a listener to changes. Does that the right structure or should each Fragment observe changes by himself ? What would the right way to handle multiple navigations between multiple Fragments
I don't see anything wrong in what you just said. Fragments should be independent from each other unless they are nested.
If you need communication between fragments that can be done in many ways. The most basic way is to do that through activity. Activity knows how its fragments interact with each other, but fragments remain independent. They can listen to events, no problem here, but make sure you have a 'rule' in your project about how you handle events.
E.g. I prefer having one listener at a time to have the order more predictable. If I want multiple fragments to handle the event, I usually place the handler in the activity and then pass the event to fragments in the exact order I need. Otherwise it might quickly get out of control.
There are other ways too, such as EventBus, BroadcastReceivers or any other event-based mechanism.
I hope that helps. If I didn't answer your question then to answer it more precisely I'd need the question to be more specific.
As the title states, does it considered as a good practice to use a single fragment within an activity to display the content? I began to notice that more and more developers start to use the fragment as an insulation layer to separate the lifecycle logic from UI that activity (sorry, fragment) displays. The most recent example that I stumble on is the architecture blueprints provided by Google developers. They use just one single fragment for UI while the activity handles ViewModel and all the navigation between screens.
So, is this a good practice or just a personal preference? Would you care to share your opinion on the subject?
Using Fragments as your UI is a good practice.
Activity can hold all common logic, while you can use different fragments to show different UI for mobile vs tablet.
If the UI is in Fragment, you can reuse it in multiple activities.
If you have a workflow scenario like Registration flow, using a single activity with multiple fragments will help you out a lot.
Manipulation of fragment backstack is a lot easier than trying to do the same with activities.
Use fragment for display the UI is good,Reason is listed below:-
1.You can create one activity,and display multiple fragment inside that activity.
2.Handling back press is easy as you can override onBackpress() in main activity class and handle back key event from fragment(s) as check its(fragment) visibility and handle event.
3. Reusability of layout.
4. Reusability of fragment.
5. Handling different action menu is very easy for different fragment(s).
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