Question
Cutting right to the chase: In Android development, is it good or bad practice to inject (ActivityScoped) LiveData instances into ViewModels using Hilt in order to observe the live data from multiple fragments?
Are there any major downsides to this approach, and is there a better way of achieving the same behavior? We could consider moving a portion or all of the code from the fragment view models to the activity view model, as the dependencies would suggest this is a better approach to begin with, but this would end up making the activity view model quite big.
Background
And some background, in case this helps to answer the question:
I have been working on an Android application in which we are using Hilt for dependency injection, Android's MVVM architecture components, and our interpretation of clean architecture which is more or less based on this article: https://www.raywenderlich.com/3595916-clean-architecture-tutorial-for-android-getting-started
Our app contains two activities and a couple of fragments, and each have been assigned their own view model. Recently as the application has grown, the code base has become a bit messy, partly due to many fragments (and their view models) depending on the same live data. The repositories and data sources injected into the view models are generally singleton, and so data sharing is not an issue.
However, what has happened is that we keep references to all view models in one activity, and many fragments are observing LiveData from each others' view models in order to update their views. This feels like a sub-optimal approach, and we are moving into refactoring season quite soon which will give us the opportunity to fix this.
Related
I have a general question about App architecture with Android. I am implementing an App (in Java) that has a single activity and 20Fragments (that are similar but not the same). So far I implemented everything in the fragments (UI, Logic, Database queries). Now I am considering to use a ViewModel but I am not sure whether it is worth the effort. So my question is whether each of my 20 Fragments should have an own ViewModel or whether I can just implement one ViewModel for all the 20 Fragments? Implementing a ViewModel for all Fragment classes would drastically increase the effort, so I would like to know if it is possible to have only one ViewModel for all Fragments?
It is technically possible to have one ViewModel for all Fragments.
However, since this one ViewModel would have to manage a number of very different use cases, it would be something like a god object. With 20 Fragments, it would have very many lines of code ...
Switching over to MVVM is generally worth the effort becasue in the long run the app is easier to test and to maintain.
It may be a good idea to have a BaseViewModel in your app: a ViewModel class which handles things which are similar in all use cases, like letting the Fragment know that it should show a loading indicator or an error message. The "normal" ViewModels could extend BaseViewModel and focus on their use cases.
It makes sense in some cases to have a shared ViewModel, for example when a Fragment shows a dialog with some EditTexts or when one has workflow with a sequence of 3-4 Fragments on a small device where on a larger device one or two Fragments would suffice.
Just in case, here's my favourite starting point for MVVM app architecture: Guide to app architecture
Have one view model for each fragment. This way each viewmodel is responsible for doing something related to one fragment and so testing is also easier.
In fact you can have multiple view models for a single fragments doing different things for you.
Keeping everything in one view model would make testing harder and also you have to keep viewmodel for all 20 fragments may be scoping to activity.
Now I am considering to use a ViewModel but I am not sure whether it
is worth the effor
This is definitely worth it if you want good for future development.
So my question is whether each of my 20 Fragments should have an own
ViewModel or whether I can just implement one ViewModel for all the 20
Fragments?
Each fragment should have its own ViewModel, I don't appreciate sharing ViewModel. I develop a lot of apps and what I've come to realize is that I should try to avoid tight coupling. Because every time you develop there will be a lot of changes and when you edit or add or remove it will make you edit a lot because the links are too tight. It would be nice to take them apart and still be able to run normally and when needed to be able to reassemble them like putting together puzzle pieces.
Implementing a ViewModel for all Fragment classes would drastically
increase the effort, so I would like to know if it is possible to have
only one ViewModel for all Fragments?
possible if you want, in programming nothing is impossible. But if you do, you shouldn't because it will only make your code more complicated.
You can read more about the model here.
https://developer.android.com/jetpack/guide#overview
You can go through with this link
Shareable ViewModel
This is pretty much easy with Kotlin by using extention function, But In Java, we need to create a function for creating ViewModel and handle their scope according to the lifecycle of activity/fragment.
I am and android developer and I have worked on all of these three architecture patterns in my applications. Also I have gone through several post's on stackoverflow about the difference of each. My understanding might not be 100% correct but this is what I know so far in brief.
MVC - User input is received by controller. Controller updates the model then tells the view to update itself.
MVP - View gets the user input and notify the Presenter. Presenter gets the data from Model and then sends it to View. Presenter and View have one-to-one relation.
MVVM - User input is received by View. ViewModel generates the data from Model and puts out a stream of data any View subscribed to it can consume that data. View and ViewModel have one-to-many relation.
The problem is that many times in interviews I have been asked the question to tell which pattern to use when. What I think the interviewer wants to know is the type of application (like banking, e-commerce, etc) and their appropriate architecture pattern. Or at least some concrete explanation as to why I would like to use MCV in one application and MVP in another and so for MVVM.
I did my research well but could not found any proper answer on the internet that talks about the use case of each pattern. Thus, request to please tell me use case for each.
From my knowledge:
MVC: Model View Controller is the traditional old way of Android development. This was used when Android development just started and was avidly used for few years. In this time, the only well known pattern was MVC.
So, mostly all old applications started as MVC but as the code base increases, the controller(Activities/Fragments) become bulky with lot of business logic and network requests and async tasks living in them. So, such applications become difficult to maintain overtime and are very harder to test due to the high dependency between the three.
So, if your application is very small and you want to follow no new architecture patterns or have 0 understanding of those use MVC but I highly recommend not to follow MVC in this time.
MVP -> As MVC applications become difficult to maintain and test, applications transitioned towards MVP.
Model View Presenter tried to resolve the problems of MVC and moved presentation and business logic to presenters. The presenter here just performs the Interface actions and has no knowledge of the Views it is trying to update. So, as presenters are not similar to controllers we can easily test presenters and models. So, we achieve testing and maintenance benefits but it also creates a problem that now presenters are the smart one. They start becoming bulky eventually. Creating a similar problem.
Also in android, apps need to maintain app state. MVC and MVP don't come out of the box to have state saving capabilities, you need to write additional code for state maintenance.
MVVM on the other hand is most popular. Model view viewModel is the new android architecture.
You can go in detail and learn this:
https://developer.android.com/jetpack/docs/guide
Network connections live in repository. So, code is much cleaner in your fragments or activities. All three components are easily tested and maintainable.
One of the biggest advantages is you have performance benefits as it does the state saving mechanism out of the box as ViewModel follows the singleton pattern and you can achieve that by using ViewProviders and creating instance through it.
When you say what application should use what. If an application size is huge and complex would highly suggest MVVM and you can also look into other popular architecture components like MVI and clean architecture(Use case based) as well. In my opinion, an application product type doesn't change architecture requirements. It's the complexity and size that determines it. Your security requirements change based on the product.
I recently started building an android application and I would like to use an design pattern right from the scratch. I was told that MVP (Model-View-Presenter) is a good pattern for android applications.
I was wondering if it's possible to implement the "Passive View" variant of the MVP pattern? If I could, I would show any code.. but right now I have no idea how a passive view should look like in an android application. Also.. which role would play the MainActivity in a passive view scenario?
I would appreciate any explanations, tutorials or examples on how to implement a passive view.
MVP pattern in Android suggests that your View classes (Fragments, Activities) don't contain any presentation or business logic, but all logic is delegated to a Presenter class. The Presenter in turn calls usually void methods provided by the View when the View is initialised, an event occurs, or the View is destroyed.
So imagine a View and a Presenter implementing the following interfaces:
public interface Contract {
interface View {
void initView();
void setTextColor();
}
interface Presenter {
void init();
void onButtonClicked();
}
}
In our simplistic example the View would initialise the Presenter (dependency injection is out of scope of this post) and then call Presenter's initView method. The Presenter would be responsible for all initialisation logic like fetching data from network / storage and, if need be, update the View. When in turn the user clicks a button the View would delegate action to the Presenter by calling Presenter's onButtonClicked() method. The Presenter can do some processing and depending on the outcome maybe call View's setTextColor() method.
The most important reason for using MVP is to be able to test your logic with Junit and a mocking framework like Mockito. Your Presenter should be written in pure Java or Kotlin without any dependencies on the Android framework library. Then you can just test your Presenter by using the JVM and not having to hook up a device. This is all part of uncle Bob's clean architecture guidelines.
The two best resources for MVP are the Antonio Leiva's blog post and Google's architecture samples in github
I have a feeling that there is a fatal misunderstanding of presenters here. Even though MVP is the common standard, most people think of Presenters as Controllers or even worse a mix of Controllers, Repositories, Gateways.
A Presenter should do one thing: to present. That should be it's sole purpose. Many people unknowingly implement a MVC Architecture, calling it MVP, with limiting the data flow as following: View <-> Controller / Presenter <-> Model.. Now there is nothing wrong about this pattern, as it separates the layers of your system, if done correctly. You should be able to swap your Domain and Data layers (Android Devs usually call the layers the Presenter and Model layer) to another system and the code should still work without any dependency issues. To achieve this you have to avoid any dependency that would cause a binding to a so called detail (UI, Database, Frameworks, Hardware, Browsers, OS). Now speaking of layers, we’d usually have this data-flow hierarchy: UI -> Domain -> Data where within Android Applications we would put all our UI Code into the UI component. Now there are 2 options to position the presenter: You could abstract the View by introducing an interface for the presenters specific view. Avoid any android / hardware specific dependencies (like Contexts) within the presenter. If you achieve this, then you could say, your Presenter belongs to your Domain layer. If your Presenter knows any Android detail (or even worse a database), then you’re automatically putting it into the View layer (or even breaking your architecture, if you try to access the database from it).
Now let’s assume you abstracted your View and have your Presenter being a Domain object. Your Presenter does not care about the actual implementation of its representing View anymore, it has its abstraction and it knows where to pass the value to. Whether it’s a mobile, web or embedded App doesn’t matter anymore.
Now how does the Presenter receive data from the Data-layer and fill the UI with data? We do the same technique that we did with the View: abstractions.
We’d create an interface / abstract class of a Repository, Gateway, DataService or however you would like to call the interface of your data/model layer. You’d have POJO, your data access logic, caching, etc. Note that until now, we’re working with POJOs! We have no dependencies to any platform-binding detail (as described above). But since we need to do some caching now, we’d have to use the SQLite Manager from Android (or Room). How to do this? abstractions. Abstract any detail that causes your code to be bound to any platform.
Below you can see a picture of Uncle Bob’s proposed design of a solid software architecture. The inner layers should not have any knowledge of the outer layers.
This picture reflects the development technique I just described here, which is the same technique described in Uncle Bob’s book. We’re avoiding any dependencies to details by using their abstractions. The real implementations (Activities, Fragments, SQLiteDatabase) are being „wired“ to the inner layers from outside through dependency injection.
This technique is also called dependency inversion.
I’d recommend you to read the book „Clean Architecture“ by Robert C. Martin to develop a deeper understanding to it.
Working with MVP is not that hard
First, in the package Model, you will store all sort of POJO classes that have setters, getters and all the data structure of your app
Then comes the presenter, where you bind this objects and do some logic on it.
After you do all the logic into the presenter, it passes all that information to the View, so after that your MainActivity (the view in this case) will have just a few lines of code and your code will look really organized.
As for passive view, it means that you have the View with the less code possible to run tests in the future and have a mantenible code.
you can use MVC, MVP, MVVM, but if you want to start I would suggest you starting with MVP
Take a look at this image of MVP
You can also check THIS tutorial about MVP
I have a project with 1 main activity and 4 fragments all inheriting from the same "BaseFragment".
When first started I managed the whole project with the same ViewModel all through the main activity and fragments but after a while, the code inside became too extensive and decided to split it in multiple ViewModels according to the necessities of each fragment/activity.
I created one "MainViewModel" and used it in the main activity and the rest of the ViewModels inherit from it.
My question is if it is a good practice for reducing the code in the ViewModel? is it perhaps inefficient to have multiple view models?
what other ways are preferred to simplify it?
Separation of concerns is almost never a bad thing. Ideally, each file/class should be responsible for one thing.
Additionally, you never know how the code will grow. Things tend to only get more complex over time, not usually simpler. So, while having multiple viewModels right now may feel like overkill, it will likely pay off later.
One case where a shared viewmodel between several fragments is ideal is when the fragments need to communicate with each other - they all would then use the activity viewmodel.
I would assume in this case you can use both approaches, though I have never done it, so I can't say for certain.
I'm rewriting a simple application to use the MVVM architecture. I got everything working, except retaining state when the user rotates the screen (or any configuration change for that matter).
While doing research I've come across several options, but I can't figure out which one is right (if there even is only one "right" way).
(onSaveInstanceState: can't be used in the ViewModel, this only works in activities/fragments)
Extending the ViewModel class. This is apparently made to make it easier to store UI-related data across the lifecycle. I find it quite confusing, and it seems overkill for what my app does. There are no async requests to online databases, feeds, or whatsoever. More than that: I can't use #Bindable anymore, so I don't know how to make the binding with my View.
Using fragments to persist state. This is used in Google's own todo-mvvm-databinding sample. I find it strange to use Fragments for this. They don't seem to be made for the purpose of just storing data.
Which one is the "best"? And why?