Android, Do I use ViewModel to perform insertion or update? - android

I understand that ViewModel in the Architecture component is for storage and managing data so it will not be lost during config changes.
For example, my activity has nothing do with LiveData or using storage Data. Should I still go through ViewModel? or directly instantiate the Repo Class and call the insertion method? I hope that make sense
An Example of my usage of ViewModel
public class MainViewModel extends AndroidViewModel {
private DataRepo dataRepo;
private LiveData<List<Group>> groupList;
private LiveData<List<Bill>> billList;
public MainViewModel(Application application) {
super(application);
dataRepo = new DataRepo(this.getApplication));
groupList = dataRepo.getGroup();
billList = dataRepo.getBill();
}
public LiveData<List<Group>> getGroupList() {
return groupList:
}
public LiveData<List<Bill>> getBillList() {
return billList:
}
public void insertGroupAndMember(Group group) {
dataRepo.insertGroupAndMember(group);
}
public void insertBills(List<Bill> bills) {
dataRepo.insertBills(bills);
}
public List<Member> getMemberList(Group group) {
return dataRepo.getMembers(group);
}
}

I think you want to use a ViewModel to keep your UI controller as clean as possible. Your viewmodel should call the repo to do simple CRUD operations.
See below snippet from documentation:
Requiring UI controllers
to also be responsible for loading data from a database or network
adds bloat to the class. Assigning excessive responsibility to UI
controllers can result in a single class that tries to handle all of
an app's work by itself, instead of delegating work to other classes.
Assigning excessive responsibility to the UI controllers in this way
also makes testing a lot harder.

Here are some points I would advice you to consider:
MVVM as a pattern has it's roots back in 2000-th, for example, here is Martin Fowler's article about the concept, and in 2005 John Gossman announced the pattern in his blog. Yes, it solves the problem with rotation in android's implementation of the pattern, but this problem could be solved without it. MVVM is actualy needen for separation of presentation state from views that are seen to the end user. As Wiki says -
The view model is an abstraction of the view exposing public properties and commands. Instead of the controller of the MVC pattern, or the presenter of the MVP pattern, MVVM has a binder, which automates communication between the view and its bound properties in the view model. The view model has been described as a state of the data in the model.
So, primarily it is (like all other GUI architectural patterns in their root) about abstraction between view and domain parts of the application, so that they can vary independently and subsequent changes to the system will be cheap.
Instantiating domain objects in the view scope and their subsequent use by the view leads to tight coupling between the view and domain objects, which is a bad characteristic of any system. Also, it is one more reason to change view's internals, because if construction logic of the domain object changes - view will have to be changed too.
If ViewModel is exessive for you (as I can see, its benefits are not relevant for you in this particular case, because the UI is not very complex and it's state is lightweight), consider using a less heavy-weight abstraction, such as MVP. Thus, you will be able to preserve abstraction between view and model in your application (no unwanted coupling) and you won't have to support the code that you don't benefit from.

Related

Android ViewModel responsibility is only hold data or hold data + controller for view?

From official we know
The ViewModel class is designed to store and manage UI-related data in a lifecycle conscious way
But i think lot of developers use ViewModel as both data store and controller(like calling repository, network client for data). I also use as for both data store and controller for view.
Android official sample code has also some controller logic. From official :
class MyViewModel : ViewModel() {
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
Here loadUsers may calling some Repository or NetworkClient . So here it acting like controller.
I am sure many developer do this way, but as from definition ViewModel should store and manage UI related data, should ViewModel act as a Controller ?
I found some stackoverflow thread this and this about this.
First one accepted answer suggested not to use use ViewModel as Controller and to use a Controller for other task.
In comment section of Second one #commonsware also suggested not to use complicated things other than data.
So my question is
What will be the actual responsibility of ViewModel from architectural concept?
If i have to do some method calls related to View [like data query, network call and other business login related stuff ] where should i do it?
and if i have to use a Controller then how i connect View and Controller for device rotation and sharing controller between Fragment ?
Hope my question is clear to all
Thanks in advance.
Here loadUsers() may calling some Repository or NetworkClient . So here it acting like controller.
I am sure many developer do this way, but as from definition ViewModel should store and manage UI related data, should ViewModel act as a Controller ?
Theoretically, the retrieval of data should be internal to the LiveData, triggered by having active observers and based on that, deciding what to do (in onActive()). If the LiveData is actually a MediatorLiveData, then this also applies to any block bound with addSource, as the block added with addSource of a MediatorLiveData is only called when the MediatorLiveData is observed by an active observer
You can see this technique used to its fullest in the NetworkBoundResource. The ViewModel only stores data, and knows nothing of data loading.
What will be the actual responsibility of ViewModel from architectural concept?
If you see the comments by Yigit Boyar (creator of ViewModel):
I'm the guy (or part of the team) that added it and it had nothing to do w/ MVVM. It is all about trying to give a class to people where they should put the data.
AAC is not an MVVM implementation, nor VM concept only lives as part of MVVM.
In fact, the main motivation for this was; we've been telling devs not to manage data in the UI controller and the answers was also, so where? And ViewModel became that answer.
We want it to be the model for your view layer (fragment, activity whatever). On the hindsight, it could be better to pick a name that is new but naming is really hard.
In conclusion: ViewModel is the Model in an MVC scenario, where C is the Activity or Fragment, V is the inflated view, and M is the ViewModel.
If i have to do some method calls related to View [like data query, network call and other business login related stuff ] where should i do it?
ViewModel gets the data in the form of a LiveData, and the LiveData is "activated" by observing it from the View with a given lifecycle.
Network calls are supposed to be also triggered in the same manner (if you follow the approach as per LiveData was designed).
In theory, if you have a login call, you could as well do it in the controller instead of the model, so you could do it in the Fragment, even though there are tricks like Jetpack Databinding that would let you call methods from the View on the Model directly from the XML.
and if i have to use a Controller then how i connect View and Controller for device rotation and sharing controller between Fragment ?
ViewModel exposes LiveData and can potentially also expose LiveEvent if you write the necessary code for that (unfortunately that is not provided by the Jetpack team, and neither are Command bindings), and either the View or the Controller can call methods directly on it if necessary. ViewModel is stored across config changes (not across process death, ofc) so it should not hold a direct view reference.

MVVM Architecture Android

I have one Activity and i have created one View-model for it. I have created different classes like
UiUtil( show, hide view, hide key board ), Network layer , Data Base layer, AppUtil( for common functionality like Collection check, String validation, Date Conversion etc)
My question is, In MVVM design pattern is Activity can use these utility classes directly or it needs to use these classes via View-model, if it via view model then in the view-model i have to write a method that just call utility classes method . like below TimeDateManager is utility class used in view-model
class HomeViewModel: BaseViewModel()
{
fun prepareTimeAmPmToDisplay(context: Context, alarm: Alarm): String
{
return TimeDateManager.prepareTimeAmPmToDisplay(context, alarm)
}
}
Architectures are not obligatory, they are recommendational, thus you can change their usage in quite wide range. The only stopper should be a common sense(if it is present of course).
In this particular case the usage of utility class inside an Activity maybe ok, based on your ViewModel construction and its way of communication with View(read Activity).
For example if you have some LiveData that sends some kind of event(for ex. data loaded from backend or alarm trigger) inside your ViewModel and your View listens to it, I think it is ok to use util classes inside an Observer in Activity. Especially if this utils method doesn't depend on any ViewModel or Repository data. The direct utils usage in Activity is not limited by this usecase, though - there are plenty of others.
I understand that this may be an unpopular opinion in modern time of "clean approach" but I believe that this "clean approach" sometimes complicates stuff where it shouldn't, thus if mixing things a bit does not brake overall architecture but rather makes some thing more readable and easy to maintain - I would go for it.
Hope it helps.
My approach toward MVVM is simple, ViewModel is responsible for business logic, dealing with repositories (Network, Database, etc.) and all of the non-UI codes preparing the required data for UI, just like the documentation:
A ViewModel object provides the data for a specific UI component, such as a fragment or activity, and contains data-handling business logic to communicate with the model. For example, the ViewModel can call other components to load the data, and it can forward user requests to modify the data. The ViewModel doesn't know about UI components, so it isn't affected by configuration changes, such as recreating an activity when rotating the device.
On the other hand, ViewModels should not store a context (ApplicationContext is exceptional) and it's preferred that they do not use android APIs at all, so they become more testable (especially in the case on pure unit tests).
Also we are recommended to make use of LiveData in ViewModels and the UI has to observe the LiveData. For example, in onCreate of your Activity, you will call loadMainContent() method from VM, it calls getMainContent(page=1) from repository, and the repository will decide to load data from DB or network, and the result will be set on a LiveData were the View is listening for changes.
TL;DR
Sometimes it's even better to call these utilities from View rather than the VM. I'm pretty sure about your UiUtil also I think TimeDateManager is more view related rather than logic related. In addition, Network and DB layers are more efficient if called through a repository (which is responsible for caching, etc.) and VM can use that repo.

MVVM. How to transfer of complex data / commands from Domain to View

Briefly, the question is: in MVVM (AAC), how can Domain (business logic) manage the display of complex states / data in the View layer?
Now in more detail.
It means that inside the Domain: 1) received, calculated some data that need to be shown; 2) the state has changed, it is necessary to react to this (hide / show a group of widgets, call a new fragment, show / update progress, etc.). And it's harder to do than just show a message or a dialog, or just send LiveData to the RecyclerView.
Therefore, examples like "hello world" or "2 + 2 = 4" do not fit, everything is clear in them. In MVP, this is simply done. But here I was able to find the weak point of MVVM.
Now I did the following.
By means of RxJava2 (as an option, it can be LiveData from AAC) from Domain to View (via ViewModel AAC) an object that contains the type of command (enum) is passed and has a bunch of fields for data for all occasions (different fields for different commands of course ).
And further, View contains a large switch-case, depending on the type of command where all this is handled.
Variant 2. To create a bunch of specific objects, and then in the View will sit a large if-instanceof.
Variant 3. Store data for View in ViewModel AAC (for which it is actually intended), and send from the Domain only the type of command, then View takes all the necessary data from the ViewModel.
Variant 4. A heap (in case of complex UseCases) a specific Observables in Domain and a heap of subscribers in the View.
So: is there (if any) a more elegant way? There may be some architecture pattern. Maybe I'm in vain reflexing, and this is the right way(s).
ps. 1) the "Command" pattern here does not exactly fit, 2) the "State" pattern has already been implemented by me, and it does not solve the problem either.
In MVP, this is simply done. But here I was able to find the weak
point of MVVM.
This is not the weak point of MVVM, it is just a difference between the implementation of MVP and MVVM.
In MVP, you create a bunch of interfaces to let View and Presenter talks to each other;
In MVVM, you create a mediator (e.g. LiveData) to bridge View and ViewModel.
IMHO, you can:
In your UserCase, create a MediatorLiveData A to store the result.
In your ViewModel, create a MediatorLiveData B to observe A (i.e. MediatorLiveData.addSource(A))
In your View, observe B to reflect any UI updates.
You can find a concrete example in iosched18.
Model View ViewModel architecture
The view is the user interface, the layout. In Android, this usually means an Activity, Fragment or ViewHolder and its corresponding inflated XML layout file.
The model is our business logic layer, which provides methods for interacting with data.
The view model acts as a middleman between view and model, by exposing the data from the model via properties and containing the UI state. Also, it defines commands which can be called on events like clicks. View models contain the presentation logic of your app.
In the MVVM architectural pattern, the view and the view model mainly interact with each other through data binding. Ideally, the view and view model should not know about each other. The bindings should be the glue between the view and view model and handle most of the stuff in both directions. In Android, however, they can not really be independent:
you have to save and restore state, but the state is now in the view model.
you need to tell your view model about lifecycle events.
you might encounter situations where you need to call view methods directly.
For these cases, both the view and the view model should implement interfaces, which are then used for communication via commands, if necessary. In almost all cases, however, only an interface for the view model is needed, since the data binding library handles the interactions with the view, and custom components can be used e.g. when a context is needed.
The view model also updates the model, e.g. by adding a new element to the database or updating an existing one. It is also used to fetch data from the model. Ideally, the model should also notify the view model of changes, but this depends on the implementation.
Now, generally speaking, the separation of view and view model makes the presentation logic easily testable and also helps with maintenance in the long run. Together with the data binding library, this means less code and cleaner code.
Example:
<layout xmlns:android="...">
<data>
<variable name="vm" type="pkg.MyViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="#{vm.shouldShowText}"
android:text="#={vm.text}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="#{vm::onButtonClick}"
android:text="#string/button"/>
</FrameLayout>
</layout>
When you want to use MVVM architecture, your layouts should only reference one variable, the specific view model for this view, in this case, MyViewModel. In the view model, you provide properties for the layout. This can be as easy as returning a String from a model object or more complex, depending on your use case.
public class MyViewModel extends BaseObservable {
private Model model = new Model();
public void setModel(Model model) {
this.model = model;
notifyChange();
}
public boolean shouldShowText() {
return model.isTextRequired();
}
public void setText(String text) {
model.setText(text);
}
public String getText() {
return model.getText();
}
public void onButtonClick(View v) {
// Save data
}
}
Here we have a text property. As we have an EditText for user input, we can use two-way data-binding, to also have the data binding library save the inputs back to the view model. For this, we create both a setter and a getter and bind the property to the text attribute of our EditText, but this time with a = sign before the bracket, which signals the library that we want two-way data binding here.
Also, we only want to show the EditText when our model says that text input is required. For this, we provide a boolean property in our view model and bind it to the visibility attribute. For this to work, we also have to create a binding adapter, which sets the visibility to GONE when false and VISIBLE when true.
#BindingAdapter("android:visibility")
public static void setVisibility(View view, boolean visible) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
Finally, we want to store the information when a Button is pressed. For this, we create a command onButtonClick() in our view model, which handles interacting with the model. In the layout, we bind the command to the onClick attribute of the Button via a method reference. For this to work directly, our method needs to have a single parameter of type View, just like an OnClickListener. As an alternative – if you don’t want the View parameter – you could also use lambda expressions directly in the layout. As you can see, it’s quite easy and straightforward to use data binding with a view model.
Now, it’s important to remember that we want to put presentation logic in our view model for testability. Avoid putting logic directly in the bindings, even though the data binding library allows it. Don’t forget that you can also have custom binding adapters, which can often simplify things.
I realized that I need to migrate in the direction of the MVI pattern.
And it is necessary to implement "unidirectional data flow".
Very well this solution is described here Reactive Apps With Model-View-Intent - Part2 - View And Intent by Hannes Dorfman
Another interesting solution is the library RxPM -- Reactive implementation of Presentation Model pattern in Android

Can I make the LiveData static?

I don't know if this is a stupid question. This may defeat the purpose of LiveData/ViewModel.
Can I make the LiveData static? My reason is I have a listener from a Service which updates the information. So I need to have a way from a service to "set/change" the LiveData.
I used to do following and it works:
1. Service changes the DB
2. ViewModel listens to the DB change
3. UI updates from the liveData change
I found this way is too slow. To increase the performance, I want something like:
1. Service changes the class object directly
2. ViewModel listens to the the class object changes
3. UI updates from the liveData change
In order to achieve what I want, either I need to make the MutableLiveData static or make the ViewModel class to share the same instance of ViewModel between Activities.
Is this good idea?
public class MyViewModel extends AndroidViewModel {
// Note: this MutableLiveData is static
private static MutableLiveData<MyModel> mutableLiveData;
public MyViewModel(#NonNull Application application) {
super(application);
}
LiveData<MyModel> getLiveDataList() {
if (mutableLiveData == null) {
mutableLiveData = new MutableLiveData<>();
loadDataFromDb();
}
return mutableLiveData;
}
private void loadDataFromDb() {
// load data from DB
// mutableLiveData.setValue(MyModelFromDb); // Omit the real implementation
}
// Note: this method is static
public static void setData(MyModel newData) {
mutableLiveData.setValue(newData);
}
#Override
protected void onCleared() {
super.onCleared();
}
}
The whole point of ViewModel from Android Jetpack (as opposed to other versions) is for the ViewModel to be lifecycle aware and perform magic like destroying itself when observer is destroyed (activity/fragment), or surviving configuration changes (for example, orientation) without initialising itself all over again thereby making it much easier to deal with issues related to configuration changes.
So if you made the ViewModel or LiveData static you would actually beat their purpose and most likely leak ViewModel's data, though the need to do this is understandable. So this requires you to engineer your way around it, and the first way you mentioned is probably the best way you can do it. I don't understand why you have an issue with the first solution. The way I see it, it provides the best user experience:
You init ViewModel in your fragment or activity in onCreate and add an Observer to the data.
If database already has some data, your observer will receive it instantly and UI will be updated with existing data instantly.
Service makes the API request and changes the DB
DB changes triggers an update to the data in ViewModel
Observer refreshes received data and you pass this to your views/adapters
UI updates with latest data with some nice animations that indicate addition/removal of items.
From what I can see it cant get better than this. Since your question is from months ago, I am curious to know what you ended up doing?
I think if MyViewModel will have lots of LiveData fields it will grow with large amount of getters and setters. And what even worst, as for me, you will break the testablity of your code, because if you will create a new instance of MyViewModel you will expect that your LiveData objects are stateless at this point of time, but as it's a static object you don't know in what exactly state it is after simple creation.
As well static methods can't be overriden. And about fields: if you will want to have common field, suppose errorMessage, in class A and class B while both of them extend class C(which contains your common field) you can have unexpected behavior. On the other hand you can duplicate this code in other classes(what is bad).
The memory issue: if a large number of static variables/methods are used. Because they will not be GC until program ends.
But it just my opinion.

Android MVP explanation

I try to understand what the best way is to program a "clean" Android app. I found an interesting article about it where they use a kind of a 3 layer architecture.
Now I read that android uses the MVP design pattern and try to understand this. The way I understand the MVP principle (in the android context) is that:
the Model layer are the logic classes
the presenter are the classes that are "linked" to an XML (the activities)
the passive view are the XML's.
Is this correct?
When this is correct, is it then also correct that the 3 layer model fits perfectly in the MVP principle because:
the presentation layer from the 3 layer architecture fits in the presenter layer of MVP
The business and the data layer from the 3 layer architecture fits perfectly in the model part of the MVP?
I hope my questions are clear because it is a complicated topic for me.
Maybe this clears up my vision (way of thinking) about this...
first thing I wanted to clarify is that MVP or any other pattern for that matter is no specific of Android dev and, can be applied to any other framework.
I think you got the gist of it:
view is usually implemented by activities and fragments and will contain the reference to the presenter
the presenter is that middle man between the view and model. Retrieves data from the model and returns it already formatted to the view so it doesn't need to do anything else but display it.
the model can be seen in a simplistic way as the "data provider". It can be as complex as you want, using internal db, lots of clases etc.
If you are interested in Android apps architecture I suggest you watch this talk given at Android dev summit this year. It is one of the bests I've seen
https://www.youtube.com/watch?v=BlkJzgjzL0c
Even though this question has an answer, I don't think this answer is complete by any means.
MVP is a general concept which can have many various implementations, some of which differ substantially. Moreover, the concept itself is very ambiguous - different people can have different concepts in mind when they say MVP. One of the most widespread ones is shown in the below picture:
Regardless of implementation, the general definitions of MVP components are:
Model: abstraction of "application state storage". The definition of what the "state" is and how it is stored are implementation details. Model implementations should not have dependency on View or Presenter.
View: abstraction of "user interface". The definition of who the "user" is and how it interacts with the View are implementation details. View implementations should not have dependency on Model or Presenter.
Presenter: encapsulates application's business logic. Presenter processes user input events received from view, and alters application's state stored in model in response. Presenter also processes changes of application's state stored in model and updates view in response. Presenter usually depends on both the View and the Model.
If you need more information about MVP in context of Android development, you can find it in this post: MVP and MVC Architectural Patterns in Android
Important issues which need to be addressed while implementing MVP in android are activity leaks which cause memory leaks and app crashes due to background process updating closed activity.
Due to presenter having reference to activity, if presenter can't be garbage collected, activity will stay in memory.
Both of the issues can be solved by using life cycle methods of activity or fragment and releasing resources in those methods so that memory leaks and app crashes are prevented.
Cleaning up of resources related background work can be easily implemented using RXJava, for more information about MVP and MVP with RXJava, see http://www.zoftino.com/android-model-view-presenter-mvp-pattern-example
Here is simplest way to implement MVP pattern in your application android_mvp_login_sample
As you have come to know basics of Clean Architechure. The following example depicts how actual your MVP pattern is implemented.
Example:
interface BaseContract {
interface BaseView {
//Methods for View
void onDoSomething();
}
interface BasePresenter {
void doSomething();
}
}
class BaseMainPresenter implements BaseContract.BasePresenter {
BaseContract.BaseView view;
BaseMainPresenter(BaseContract.BaseView view) {
this.view = view;
}
#Override
public void doSomething() {
if (view != null)
view.onDoSomething();
}
}
class DemoClass implements BaseContract.BaseView {
//Create object of Presenter
/****
* Example :
* BaseMainPresenter baseMainPresenter = new BaseMainPresenter(this);
*/
#Override
public void onDoSomething() {
//Deal with Context here.
}
}
Refer below link for sample Actual implementation with scenario & learn more about Clean Architechure : https://github.com/android10/Android-CleanArchitecture
Here on github
https://github.com/saksham24/Android-Firebase-Mvp-Mvc-Mvvm-chat
i made a repo containing 3 applications with same functionality but written in 3 different android patterns(Mvc, Mvp, Mvvm)
Understanding three different pattern is quite easy if we get a simple good example on them so i made a repo to contribute my knowledge to this developer community.
Also the repository is written using proper java guidelines and conventions(including naming and packages, modules) so people looking for such project can also view this repository.
now
if you want to know the difference between android Mvp,Mvc, MvvM see this explanation by realm
https://academy.realm.io/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/
if you want to compare three pattern see this wonder full blog https://thinkmobiles.com/blog/mvp-vs-mvvm-android-patterns/
Now I read that android uses the MVP design pattern and try to
understand this. The way I understand the MVP principle (in the
android context) is that:
the Model layer are the logic classes
the presenter are the classes that are "linked" to an XML (the activities)
the passive view are the
XML's.
Is this correct?
Not fully: for the Model layer it is true, but for the Presenter it is not. The Presenter is not linked to XML although it has reference to the View through its constructor. The View is the Activity/Fragment in android.
You might want to check here for a sample MVP app for android.

Categories

Resources