View Model can be heavy if we use single activity based architecture - java

As google suggests single activity based application. I have a situation where I need clarification.
I have one activity containing 3 fragments and each fragment is linked to different fragments having other screens.
should I use only one viewmodel for each tabs or should I use one view model having different screens.
As I have only one activity and view Model resides till activity is destroyed. Do all viewModel that I will create for each screen will contain data until activity is destroyed. If this is the case will it make my app heavy.

should I use only one viewmodel for each tabs or should I use one view model having different screens.
You should use the smallest scope for each ViewModel possible. Generally, this means that data associated with only one fragment should use a ViewModel associated with just that one fragment.
As I have only one activity and view Model resides till activity is destroyed. Do all viewModel that I will create for each screen will contain data until activity is destroyed. If this is the case will it make my app heavy.
ViewModels live only as long as the ViewModelStore they're attached to is around. Therefore if you have a ViewModel associated with a fragment, it'll survive only as long as that fragment exists. For example, if that fragment gets popped off the back or you call remove(), then the ViewModel is destroyed. ViewModels only live as long as your activity if you specifically create them using the activity as the ViewModelStoreOwner (for example, by using ViewModelProvider(activity)).

should I use only one viewmodel for each tabs or should I use one view
model having different screens?
In single activity architecture, you can use ViewModel with either Activity Scope or with Fragment scope. As #ianhanniballake suggested in his answer, use ViewModel with Fragment which means that each tab in your case will have its own ViewModel attached to fragment. This will provide separation of concerns for functionality in each tab.
As I have only one activity and view Model resides till activity is
destroyed. Do all viewModel that I will create for each screen will
contain data until activity is destroyed. If this is the case will it
make my app heavy.
Again answer to this question is connected to your first question and explanation provided to it.
While working with single activity architecture narrow down scope as much as possible. Use ViewModel associated with activity (lets call it Global ViewModel) only to keep data which is used across multiple fragments. This way viewmodel will contain data till activity is in backstack and fragments can use it when required.
This will provide you 2 advantages
ViewModel will not contain additional data which you mentioned in your 2nd question
And most importantly there will not be any data discrepancies while accessing fragment multiple times. For e.g. if you open any fragment, fetch data from api and keep it in Global ViewModel and fail to delete it when remove fragment from backstack then your fragment will show old/obsolete data when you will open fragment next time. To avoid this scenario it is better to keep this data in viewmodel with fragment scope.
I hope this will be useful.

Each Fragment usually should have a ViewModel itself but in some cases where you want to share the same ViewModel instance, you can achieve it with having a ViewModel scoped to an activity.
ViewModel objects are scoped to the Lifecycle passed to the ViewModelProvider when getting the ViewModel it is found on the docs and you might have to read other details there but technically you can scope a ViewModel to a Fragment or to an Activity.

Related

Question about BottomNavigationView in Android

I have general questions about BottomNavigationView. I would like to have a BottomNavigationView in each of my Activities in an App for ordering something (e.g. food). It should have 4 buttoms:
Back
Info
Stats
My Orders
With 'Back' the app should just go back to the previous activity. The buttoms 'Stats' and 'My Orders' should switch to a persistent activity that should not be destroyed when not being displayed. 'My Orders' should display the last orders. The buttom 'Info' should only display some information about the current item or current menu (depending from which activity it is called). So basically I have 2 questions:
Should the Activities 'Info', 'Stats', and 'My Orders' be real Activities or just Fragments? Normally I think that at leat 'Stats', and 'My Orders' should be real Activities as they are persistent. But in many BottomNavigationView only Fragments are used?
How can I pass content information to the Activity/Fragment 'Info'. This Activity/Fragment should display information based on the Activity is was called from. Let's say the Activities are different dishes. Do I have to create a separate Info-Activity/Fragment for each dish? Or can I somehow define a dynamic Activity/Fragment that displayes information based on the current Activity?
I'd appreciate every comment and I'd really appreciate your help.
The recommended approach is Single Activity and Multiple fragments.
You can do this using Jetpack's Navigation Component
In case you need to pass data from an Activity/Fragment to the new calling Fragment, it can be done by setting arguments on the calling fragment and then getting it on the called fragment. If there is something which requires to be dynamic, for example- dishes fragment, make a single fragment and common layout and load the data dynamically from the backend.
For Setting Arguments, this should help
How to pass a variable from Activity to Fragment, and pass it back?
Note: You can use fragment without using Navigation Components but you have to use FragmentManager and FragmentTransaction and also have to maintain the Backstack by yourself which could be quite complicated

MVP Android: how to pass data from one activity to another?

I have the following doubt and I'm wondering if this breaks or not the MVP pattern.
My project has Activity1 where an user can fill a form and then the presenter, related to that activity, on a button click retrieves data from a database based on the information given by the user and put it into a list.
Activity2 has the job to display the objects of this list.
Is it ok (according to MVP) that Activity1 put the list into an Intent and then start Activity2 with that Intent? (I don't think so).
Should the presenter of the Activity1 pass the list to the presenter of the Activity2? But how can this be done if presenters can't communicate each other?
Personally I use a single Activity with Fragments which makes it easy to pass data around. For inter-activity communication, I just use Intents as you have suggested.
If you're using Kotlin you should check Navigation Component related topics.
Navigation component is the a best practice when navigation between Activities/Fragments and allows you to pass data as arguments between them.
On the other hand you can pass those arguments in your intent view Bundle and retrieve them in the second activity, separating the logic from the view layer, and only calling a method to present the data.

Do fragments keep running even if not on screen?

I have a Android app that shows lots of real-time data jammed onto one large scrolling activity.
Now i want to split it up into two simpler screens using fragments, where only one fragment may be on the screen at any one time.
I read up a whole lot on fragments and watched several videos, but before i start ripping up my code to convert it to fragments i wanted to know the following.
If i create two fragments A and B, then while showing fragment B, data comes in for fragment A. Can the controlling activity still communicate with fragment A giving it data even though its off screen? OR do i have to save the data somewhere and then when the user switches to fragment A then I give fragment A the data to be shown, while saving incoming data for fragment B which will now be off screen?
The problem is that right now im not saving any data because everything is on one screen, so as data come in i just displayed it, but if i switch to using fragments i dont know if i can do the same thing by passing the data to the fragments even if they are not on screen at the same time.
Thanks.
If you retrieve your data with multiple asynchronous requests in your Activity, you may create a fragment for each of them and move related retrieval operation into that fragment (probably to oncreateView() method). Then, you can use ViewPager (probably with TabLayout) in the parent Activity to be able to use all those fragments. Therefore, your Activity only deals with setting the ViewPager and leave the rest to fragments.
ViewPager shows one page at a time but it can initialize other fragments as well, even before they are shown. You can use ViewPager's setOffscreenPageLimit() method to increase that range.
In case you need a communication channel between fragments and the activity, you may create callback mechanisms, as described here.

Android Fragment: Fragment should manage itself being shown/deleted

it is me again and i first wanted to apologize for asking that much today.
Here is my situation.
Because of my design my FragmentActivity( topmost parent in obiect hierarchy) has only one member, which for itself has a collection of objects like fragments, i have one level between fragmentactivity and the fragments. I would like to avoid some kind of event bus and/or observable pattern to pass the events of the fragments buttons to my object which would forward them to fragment activity to be then handled there.
Especially showing fragment, deleting replacing fragments is preferred to be handled in my object in between or even in the fragment itself.
Is this recommended? Or will I get into any trouble?

Fragments onClick method in fragment element

I read quite some articles about fragments, but I am still confused about how to do what.
I have a MainActivity, which displays two fragments side by side. In one of the fragments I have a button and defined in the fragments layout XML for the button
android:onClick="buttonClicked"
Now I want to implement that method
public void buttonClicked(View view)
I would have assumed that this has to be implemented in FragmentA.java and not in MainActivity.java. But it only works if that method is implemented in MainActivity.java. Why is that? To me that doesn't make sense. Pre Honeycomb a method belonging to one activity stayed in that activity, now on a tablet I am merging many activities to one MainActivity and all the different methods are merged? Whatever do you put for example in FragmentA.java then? What if you have to start you an own activity because this app runs on a handheld, then the onClick method has not to be in the MainActivity but in the Activity which needs to be called then. I am pretty confused at the moment...
I'm not sure what the specific problem is, but maybe this will help.
From the Android documentation on Fragments:
You should design each fragment as a modular and reusable activity component. That is, because each fragment defines its own layout and its own behavior with its own lifecycle callbacks, you can include one fragment in multiple activities, so you should design for reuse and avoid directly manipulating one fragment from another fragment.
That is, you should never manipulate a fragment from another fragment; rather, this should be done through the underlying Activity. Read the "Creating event callbacks to the activity" section in this article for more information (it's important stuff!!).
On the other hand, if you want the button to perform an action within the Fragment itself (i.e. if you wanted a Button click to change the text of a TextView within the Fragment), you should implement this in the Fragment, not the Activity (this is because the resulting behavior is contained within the Fragment and has nothing to do with the parent Activity).
Leave a comment and I can clarify if my post is confusing... I only recently began to understand Fragment's myself :).
Well,
I guess it is related to hierarchy of android context structure.
Activity is host of all child views and hence you can say fragment is actually using its host's context.And that's why when you use onClick with fragment system always searches it in Host activity of fragment.
Check it on.
Android developer onClick attribute description
I haven't checked one thing but you could put a test.
By providing implementation in host activity rather than in fragment,but use onClick on layout file of fragment.It should call parent's method.

Categories