Activity with multiple ViewModels - android

I have an Activity that contains 3 RecyclerViews. I need populate RecyclerViews with data from remote repository (3 different requests). Can I use multiple ViewModels in the Activity, or is there any better solution (best practice).

According to the open/closed principle, you should create three different ViewModels. The complexity isn't increased that much, and you are gaining the ability to move one ViewModel (or just reuse it) with the corresponding RecyclerView to the another Activity very easily.
Of course, sometimes breaking rules makes sense - for example if you know, there is no chance, that RecyclerView will be reused or moved to another screen, and then you can go for simpler solution with one ViewModel.
The same situation if the ViewModel (even with the 3 lists) is likely to stay always very simple (just three LiveData fields, just a few lines of code to populate them), you can break this rule.
However violation of O/CP is not a good practice - it's just a conscious breaking of rule.

In this case I would recommend to use one view model which populates three different LiveData objects. This way the UI can get updated whenever one of your three requests gets a response. For details how to use a RecyclerView with LiveData take a look into the Google Example.
I think having multiple viewmodels per activity only increases complexity and I do not see any value in doing that.

I got two recyclerview in a fragment. I think that use two ViewModels would be better. Cause different recyclerviews got their own data request, and state handling especially connections error.
In this case separate into different ViewModels would not increase the the complexity, but I think it well fit the rule of decupling

Even simpler, you can have one ViewModel, that uses one service class, which in turn uses the three repositories to get the data. For example:
XActivity --> XViewModel --> XService --> {Arepository, Brepository, Crepository}

Related

Does a BottomSheetFragment need ViewModel?

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

Model View Presenter - same view, different presenters

I'm building one Android app using MVP, and I have one question about this pattern.
Say I have one screen for creating a new person. This screen will show one EditText for inserting the name, another for the surname, one ImageView to show the picked photo picture, etc.
This will lead to one View interface, implemented by the Fragment. It will cooperate with one Presenter interface, implemented by another class.
Fine.
Now I have another feature: a screen for editing an existing person.
As it happens, the View for this feature is identical to the one for creating a new person. However, the Presenter is different. It will start by loading the existing person from db to pre-populate the view with the current data, and the action over the database when clicking "save" will be an update instead of a insertion.
So, I think this is an example of MVP where one View works with different implementations of the presenter to achieve different use cases.
Do you think this is a correct assumption, or do you think different features should have different View and Presenter interfaces?
Also, if you'd with a common View and different Presenters, will the implementation of the View be common, or would it lead to the same interface implemented by two classes? In practice, I see two options.
Having just one Fragment implementing the View. Depending on whether the user is about to create a new person or update an existing one, the Fragment should receive and use a different Presenter.
Having two Fragments. Each one would instantiate a different Presenter. Use composition or inheritance to avoid replication of code between the two fragments.
What do you think is better to do in these cases?
Thanks.
You'll run into this when you create a CRUD-like application using the MVP pattern on Android.
You can very easily just have the single view, as long as you document well in your class that it impl the 'view' for two different presenters, then it 'is okay'
I would personally suggest creating 2 views, one for 'create' and one for 'edit' (They might be the same(for now), but separating them makes it clear that they -are- different things.)
You could easily see a situation in the future (or another impl of this pattern) where your 'create' and 'edit' views actually have different APIs. Or slightly different visual cues, such as a button labelled 'create/add' in one and 'update' in another.
I'd personally make a view-library/helper class that both Views pull logic from. This should help you reduce overall LoC, even if you make 2 'view' classes. The benefit of this is that you change either the Create/Edit views easily without worrying about impacting the other. (I tend to think the 2 view files, would be easier to maintain down the road when there is even a 'slight' variance between Create/Edit)

When would you reuse a fragment?

I am planning an app and trying to explore all the possible development options/methods I have available. One thing I'm struggling to get my head around is Fragments. I see a lot of people praising them as you can "resuse" fragments throughout the app but I can't think of an example situation.
From some example apps I have looked at (all been tabular layouts) the code for each fragment has one layout, so why not have a seperate activity instead?
I am hoping to implement a tabular layout in my app. If anyone can give me an example of a fragment being reused within an app I hope it will give me a better understanding of the benefits.
"Reuse" is overrated. Of course - you can put this same fragment (with this same features) in different places of your application - let's say that you can use a fragment in different, horizontal and vertical layouts (as you probably saw in Google's tutorial).
But at the end using fragments simplifies your project - for example - you can switch fragments inside one activity and get benefits of much easier navigation and in app communication.
Using fragments gives you one more thing - flexibility. It's much easier to move some view from one place to another, or just remove from application. All that because fragment encapsulates logic and usually a view, still offering power of externally managed lifecycle.
(Thanks for comment from Richard Le Mesurier)
Fragment is not a View neither a ViewGroup. It is not a visual element at all. Fragment inherits directly from Object.
One should think of a Fragment as a unity of a reusable code, reusable in various Activities (the Activities consist of visible elements).
Thus if you can think of any code you can reuse through several Activities (even the same Activity with different layout) and that code somehow depends on Activity lifecycle, then you probably should make this code a Fragment.

Android: Replacing the Views of the Layout dynamically

In my application i want user to fill in a large form (5-10 fields). Not all the fields are EditTexts, some are Spinners, RadioButtons etc.,
So instead of have them all in a single layout(user may leave the screen, seeing so many questions). I thought of having it as a Conversational/ questioner like thing.
On submitting each answer eventually shows a new question.
Instead of having separate Activity for each question, better i change the ContentView of the same Activity.
Solutions like:
1. Make View's Visibility Visible/Gone depending on the question to be asked
2. Change the ContentView and all onCreate().
are inefficient when i have to change the ContentViews or Visibilities 10 times.
Should i use a Fragment in the Layout and replace it with new Fragment?
Even that way i end up having 10 Fragment classes and 10 layouts 1 each for th Fragment Classes.
Is there any other way to implement this. Right now i am doing it using Fragments.
Thank You
I believe, Fragments would be the best choice here, since either ways (i.e. either dynamicaly or creating layout files) you have to write it 10 times.
So better would be Fragments, since, each layout will get replaced with the previous layout dynamically.
But you also have to consider one situation here,that is, if in future, you have to add new questions in your form, then you will have to do a lot of modifications in the code, otherwise, this is the best place to use Fragments.
I had a similar situation where the user had to fill in a few requests, there was a status and navigation pane which remained constant throughout the app, so it didn't make sense to start a new activity every time. So I made a main layout with a three Linear layout utilising the top and bottom for navigation/status and the middle was used to display the questions.
I created the different layouts and inflated/deflated them as required since i had only a few (3) layouts. If the number of layouts increases then the method to keep track and inflate/deflate them might become complex.
Adding and removing layouts/questions is rather easy, if you have a sequential flow. One downside to this approach is the backstack, you have to implement the logic yourself as you stay within one activity and a backpress will exit the activity. This approach also has some advantages since all the data you collected in the questionare is readily available and is a boon if your next questions are based on the previous answers, it reduces a considerable amount of work in having to pass them along in intents.
However, I do not have much experience with Fragments since I opted for this approach since it was much simpler than fragments and required less time to implement for my requirements.

Why use Fragments? [duplicate]

This question already has answers here:
What is the benefit of using Fragments in Android, rather than Views?
(6 answers)
Closed 10 years ago.
What is the advantage to using Fragments over using custom Views that are reused in different layouts?
In the original blog post introducing fragments, Dianne Hackborn says that
[Fragments] make it easier for developers to write applications that can scale
across a variety of screen sizes, beyond the facilities already
available in the platform.
and she goes on to explain Fragments in the context of making a tablet layout for an app that combines the UI of two activities from the phone version of the same app.
But it seems that the same reuse could be achieved using custom Views. The main different between Fragments and Views seems to be that they have differing lifecycles...
The Fragment lifecycle is:
onAttach(), onCreate(), onCreateView(), onActivityCreated(), onStart(), onResume(), onPause(), onStop(), onDestroyView(), onDestroy(), onDetatch().
The View lifecycle is:
ctor, onFinishInflate(), onAttachedToWindow(), onMeasure(), onLayout(), onDetatchedFromWindow()
I'd like to hear from developers with experience writing large apps about what benefits (if any) they've seen in using Fragments vs custom Views to divide up the UI into reusable pieces.
The main reason is that fragments are more reusable than custom views.
Sometimes you can't create a fully encapsulated UI component relying on views alone. This is because there are things you would want to put into your view but can't because only an Activity can handle them, thus forcing tight coupling between an Activity and a View.
Here is one such example. Lets say you want to create a reusable UI component that, among many things, want to capture a photo and do something with it. Traditionally you would fire an intent that starts the camera and returns with the captured image.
Notice that your custom UI component can't fully encapsulate this functionality because it will have to rely on hosting Activity's startActivityForResult because views don't accept activity results (they can indirectly fire an intent through context).
Now if you wanted to reuse your custom UI component in different activities you would be repeating the code for Activity.startActivityForResult.
Fragment on the other hand cleanly solve this problem.
Similarly your fragment can contribute items to your options menu, something traditionally only an Activity could do. Again this could be important if the state of your custom view dictates what goes in the menu.
A fragment is way more than just a view. In fact it can even be totally without a view. It can have all sorts of stuff in it including AsyncTasks, various Listeners, file and database access and so on and so on.
Think of it as a small activity, but you can have multiple of them on the screen and work with them all including communicating with each other while they are visible.
E.g. you could have a list of shopping cart displayed in one fragment and the currently selected cart in detail in another fragment. You then e.g. change the quantity of an item in the detail view and the list view could be notified about it and update the total price in the list view. You can totally orchestrate interactions like that nicely while e.g. still having only one of them visible on a smaller screen device.
I have refactored a large business app (>15 activities) from activities to fragments to get good tablet support and I would never start a new app without fragments.
Update Feb 2016: While the above still holds true, there are complexities with fragments that caused many people to entirely avoid using them. Newer patterns such as usage of MVC approaches and more powerful views provide alternatives. As they say .. YMMV.
Some description:
Imagine Activity as a plate that hold one big cake.
Fragment would be a container that slices the same cake into pieces.
Each slice contains it own logics (listeners, etc).
And in total they are almost no different with the one big cake.
The benefit:
When you plate can't hold a big cake. (Screen is small) You can easily use a a few plates (Activity) to hold each of them WITHOUT the need to move your logics into the new activity.
Better re-usability. I have some instances where I could reuse a fragment entirely in another App. You might claim that a custom view could does that too. But refer to point 1, I could reuse it with just few lines of layout changes but for a custom view, it have to find a way to plug it into both layout and code.
It is, in some sense, a more OO ways of organising your UI logics in Android programming. When you have a feature (A new partition on the screen for example), you create a new Fragment class, with minor modification to existing activity class. However if you are programming only with activity, you will need to add logics and make big modification on tested class.
Just my 2 cents. :)
The lifecycle methods are probably your biggest hint. If you think about it, they correlate closely to the activity lifecycle (with some hooks into the activity and views). In fact, in the article you linked, Hackborn says:
In some ways you can think of a Fragment as a mini-Activity
As with many things in software design/development, there are a multitude of ways to do things. There are many different places you could put your code. Yes, you could probably put a lot into a view, but keeping different concerns separated in different classes is a good thing though. The classic pattern of this is MVC and it applies in this scenario. You don't want to bake in too much controller logic into your view. It's better to keep it in controller-like classes which are the activity and now the fragment. This is why the fragment's lifecycle is more like the activity's than the view's--it was made to facilitate this kind of organization.
I touched Fragments once and found them not very useful (see this post). From what I have read, A Fragment is really a fancy word for an Object with access to Activity Context. I like to ignore Fragments in my work, and just create these Objects myself. I have created very large, very demanding apps by passing an Activity to constructors, instead of Context. One major benefit, however, for using Fragments is that they are supported by the View layout system - so you can easily add them to Android xml (if you use it for your layouts).
Custom views are much more work than just using fragments in place of your activities. if you decide to use Activities and custom Views, you have to create your custom view, and then you have to implement the same activity lifecycle methods in your activity (a very similar lifecycle is used for fragments).
Using Fragments also allows you to separate components into their own classes (Fragments), rather than having too much logic in a single Activity. Let me ground that with an example:
Say you're implementing a magazine reader application. using fragments, you could create a fragment: ArticleList, which displays a list of articles, and another fragment: ArticleDisplay, which handles the logic for displaying content. you can then specify how these fragments should interact using the fragments tools, so that on a handset, you can use the full screen real-estate for ArticleDisplay, while on a tablet, you can display the fragments side by side.
If you were to attempt this with an Activity/custom view, you'd have the logic for both Fragments in your monolithic Activity, you'd have to write a custom view, and you'd have to debug this unwieldy monster.
Fragments are, in general, a more sophisticated and powerful way to write your applications. They can do everything an Activity can do, and more. If you don't need the extra functionality, the defaults will probably get you where you need to go, and with less work.

Categories

Resources