In the MVVM architecture, where does one start an activity for result ? For example, I need to get banking informations from an nfc tag in my payment app. What I do is I start the ReadNFCActivity from my PaymentActivity, retrieve the results there, and then I call my PaymentViewModel's updatePaymentInformations(name: String, account_number: Int...) method from my PaymentActivity. The data going from one activity to the other before being sent to the viewModel doesn't feel like the right way. How would you structure this ?
Any help will be appreciated !
In MVVV you shouldn't gather or keep data in your views. In your example you shouldn't get data from the card in the view. You can get the data from the card in the viewmodel and save in a Livedata variable. Whenever you need to display the data you can observe this Livedata. Handling the data this way can help you in complicate lifecycle aware data management scenarios.
Its better to think of Activities as containing a view not the view itself. Meaning showing stuff on the screen is not it's only purpose it is also a/the context of the app which allows access to OS functionality and resources.
Unlike Windows where you can access OS functionality and resources anywhere making MVVM trivial, instead in Android you have to access it through a context, which is the Activity/Application.
IMO
If your activity is starting another activity for a result than its well with its right to do that, because its the context. Passing that result to the view model is no different than sending input from a listener to the view model like text input.
If the view model isn't touch the views than you view model is good to go.
Related
I understand that the advantage of the MVI pattern is that it is a single-state flow. So is it really necessary to have only one state model in MVI?
My app has several activities, and the subject of data obtained for each activity is completely different. For example, activity A gets the dog's information, and activity B gets the information of a Github user. In this case, if MVI-pattern should be only one state model, the mvi state model contains all the data information of activities A and B?
In most cases we're talking about single-state per ViewModel. And ViewModel is (usually, but not always) bound to a single screen. There is absolutely no incentive to store whole application state in a single object, that would get out of hand really quick
Adding to the accepted answer, Mvi is one of the presentation patterns, which addresses and try to solve the presentation problems. so by presentation we mean Single Screen whether it's an Activity, Fragment or Ui controller.
So with screen A, you'll have uni directional flow to get the Dog's information, and another one to Screen B, and so on.
I am working on a small application using MVP pattern. My home activity has viewpager with multiple fragments in it and each fragment has its own presenter. Fragments aren't communicating with each other so the activity doesn't have any logic, it is just initializing fragments on start.
So if I would like to implement the pattern by the book and stay true to its principals should I implement presenter also for the activity? And if so what should be its role?
If you want to implement MVP by the book and stay true to its principals, every UI that has user interaction should have a presenter. In this case, if your activity is not interacting with the user, there is no need to have a presenter, and your fragments can have their own. If your activity needs, let's say show a loading to the user because of some data loading prior to show the fragments (this is a user interaction because you are interacting with the user to let them know that something is happening so they should wait), then might be good to consider having a presenter for the activity.
MVP doesn't care at all about whether is an Activity/Fragment/View, it just knows View which is considered as an abstraction of whatever can be shown to the user :)
That is at least, from the 'rules' perspective. My 2 cents is, be flexible, if you see that it actually ends up adding value to you and your project, do it, otherwise, sometimes you have to 'break' the rules or create your own.
For using the fragments with their own presenters, I try to use the presenter-contract classes duo to manage the UI events in the fragments.
For example, Consider a click event to show a toast message in case of two possible outcomes: 1. Save and 2. Delete
Then, I will declare two view contract methods like this:
interface View{
fun showSaveMessage()
fun showDeleteMessage()
}
And then, in the fragment, I will use an instance of my presenter class to display the messages at appropriate times like: presenter.doSaveAction(), the presenter in turn will cause the view to show the toast message.
Also, when I come to the actual logic of the fragment, like for fetching some data from a remote server, I use Interactor class along with the Presenter-View classes to perform it.
I believe staying true to all the principles is virtually dependent on what kind of application you are building. Sometimes, it is more feasible to use MVVM with MVP than only MVP pattern for the app architecture too.
I hope this answers your question, kind of?
This is the 'like' feature on Facebook.
I would like to synchronize these recyclerviews with these two pieces.
If you click on the 'Like' button on the recyclerview in one piece, the 'Like' button on the recyclerview should change when you change to another piece.
Which method should I use?
interface?
service?
Map Should I use this?
What method do you use to synchronize the data of two fragments?
You should be using ViewModel's from architecture components.
https://developer.android.com/topic/libraries/architecture/.
Basically you create a view model in the activity so that it is stored with the activity scope
//this is the instance of the activity
ViewModelProviders.of(this)
You can then get an instance of this view model in each fragment using
ViewModelProviders.of(getActivity())
The view model can then be used like in a standard MVVM architecture.
Each fragment should register to the lifecycle aware components that the ViewModel would provide. MutableLiveData is one such component that you could use to provide the data back to whoever is interested in the data (in this case each fragment)
Be aware that LiveData while does a fantastic job can be limited as it stores data as a state in time. This is great, but android should be developed where it is driven by events)
As an example If you have a viewmodel which sends data to the view via livedata it could trigger a dialog. When the user closes that dialog and causes a configuration change (destroys and recreates the activity) the view will receive the state of the live data at the point in time it was set which will again show the dialog. Basically each time you rotate the device it could show the dialog agian even though you've dismissed it.
A hacky fix to this is to notify the viewmodel to remove the state in the livedata after the dialog is dismissed. but this creates a number of other issues including tying view state with the viewmodel
It's a lot more flexible if the Lifecycle aware component instead sends events of when data changes. Think Rxjava that is lifecycle aware. You add the data to the RXJava component and the observable provides the data to the observer when the view is in a state to consume it (> onresume and < ondestory).
Hopefully that gives you a starting point. Let me know if you need more details
TL;DR
How do I deal with Activities that actively change data (for example through an EditText)? Do I keep saving their state in the SavedInstanceState on rotation and only use the ViewModel when all of the fields are ready, or is there a way to make the ViewModel responsible for checking/holding/using the UI's data?
Question
I'm developing my application using Google's Arch. Components, and writing my latest class I've noticed I'm not really sure on what the best practice is when handling, say, data coming from an Activity form.
Example
I have a POJO made of title, description, location, type
I have an Activity with four EditText: title_et, description_et, location_et, type_et.
My ViewModel, through a Repository (irrelevant here), can send an object to the Database when the sendObject function is called.
How I'm doing it now
The activity has the mTitle, mDescription, mLocation, mType.
On rotation, the activity saves all of the EditText values in the savedInstanceState bundle, and it loads them again populating the views.
When the user wants to send the object, it clicks a button and the activity calls the function viewModel.sendObject(mTitle, mDescription, mLocation, mType) after the necessary checks.
Problems with this approach
The activity is responsible of holding/checking all the data of the EditTexts, basically making the ViewModel only responsible of interacting with the Repository.
What I'd like to accomplish
Ideally, I'd want to make the Activity only responsible of the UI, delegating everything to the ViewModel.
This way I could call sendObject() and the ViewModel would have already all of the data needed.
The LiveData situation
Right now the ViewModel has only one instance of LiveData, inside that there is a Resource (which is taken from here) and it's used to "tell" the Activity that new data has arrived or an error occurred.
This approach works fine in all Activities that just receive data from the network and display them. What do I do when I want to synchronise data coming FROM the Activity? Do I use one LiveData for each field and use that to display potential errors?
I've read most of the samples but all of the Activities there are passive.
Conclusion
Thanks to anyone who takes the time to help.
You can either separate the logic into a model string class with another class containing all your String values for the edit text fields are just assign the String values at the top of your class.
You can have a LiveData of your model in the ViewModel and alter it from the View (Activity/UI). The downside is that to update the LiveData, you need to copy whole Model, edit it and post it back to live data.
The second way is to dissect Model's components in the ViewModel into individual parameter LiveDatas. Later when form is submitted you can reconstruct the Model.
What you can do for native fields is use data binding. For other you need manually update LiveData from the View with listeners etc.
I read about MVP patterns. When we are starting developing android applications we are almost by default using MVC (we usually have our models in "models" package, views are inside "res" folder and activities are basically controllers.
I have realized that some activities inside my applications are not very readable, they are easy to understand but it take some read it because of the amount of code (for example,set up listeners for seekBars, handling sending data do AlertDialogs,receiving data from AlertDialog, validation of data before sending to server.
I don't see any benefit of starting using presenter (in MVP pattern). Presenter holds reference to activity, and when I want to do something with my view(change some EditText for example), I will call some method on presenter that points back to some method in my view(activity).(Explained here) All interactions with views are still handled inside activities which makes it hard to read.
Currently I implemented presenter layer just like some facade layer above activity. For example, there are methods like BindModelToUiViews() that have lot of code for setting up initial views(controls) on screen. What is best practise to make android activities "clean" and more readable(maintanable)?