Presenter/View/ViewState relationshipts - android

For example, I have EditProjectFragment which contains few elements:
TextView (project name)
ColorPicker (project color)
Spinner (project type)
Let's see:
Project name will be restored by TextView itself
Who must store project's color?
Who must store spinner's value?
It seems to be ViewState's responsibility. For example, when user picks color, View calls presenter.onProjectColorPicked(color). Then, Presenter will call view.setProjectColor(color). Or View should update ViewState directly, without calling Presenter if it doesn't need?
Another example. User adds photo in EditNoteFragment. User picks photo(presenter.pickPhoto()) -> presenter.addPhoto(photo) called and notify View to add photo to ViewState&show it.
Should View update Note object by itself? Should it be done by Presenter? In the first case it means that ViewState will provide methods like getNote()/setNote(note) that will be used by View. Should I duplicate Note-reference via updating it in View.setNote(note) method? The second case means that I probably should store Note object in Presenter and just update View without passing Note in it. But it looks like a wrong way.
In other words: what View must do without Presenter's help(add a photo to Note object?) and what things with it(button clicks etc)?

Viewstate was meant to be used to represent different states from your View. I.e The view is displaying a loading indicator. so we could say that the view is in the "loading state". So whenever the "state" changes usually a presenter was involved because its the responsibility of the presenter to coordinate the views state. The question is: how do you define state? There is no silver bullet.
I don't think that it makes sense to play such a ping pong game like
presenter.onProjectColorPicked(color)
view.setProjectColor(color)
unless, you say that it goes down to the model (business logic) like this:
View calls presenter.onProjectColorPicked(color)
Presenter calls model.setColor(color)
model informs presenter (via observer pattern) that the model has been changed
Presenter calls view.setData(newModelWithChangedColor) containing the new color
In general: the view is just displaying (via presenter) what the current state of the "model" is.
ViewState is just a little helper to deal with screen orientation changes and process death in a slightly more convenient way (compared to traditional onSaveInstanceState(Bundle) implementations).
So ask yourself: What is the state of your "model". Usually, the view's state is the same as the state of the "model".
In the first example, it seems that it is an issue of color picker and spinner to not save the the picked things internally. Therefore, doing that manually in onSaveInstanceState() for the picker / spinner is the default way the android team recommends to go. So, if you just want to use the ViewState feature to not use onSaveInstanceState() because you find it more convenient to use ViewState then this is fine too, although it is not exactly what ViewState was meant for.

Related

How to Implement MVI in Android using just Java

Please does anyone have a link to a resource that helps in learning how to create an app using mvi design pattern but all code should be in Java and not Kotlin
Before you click! This is in Kotlin -> https://tech.olx.com/mvi-architecture-in-android-a-simple-livedata-based-approach-b4b23896fd32 But if you actually look at the code snippets there is not a single line that doesn't have an obvious Java counter part. There is not a single Kotlin exclusive item like Flow, Scoping, Coroutine anywhere.
You don't need to learn Kotlin to understand it, just read it.
The article explains MVI as a modified way to use a MVVM.
It has 2 (ViewState/ViewEffect) components that are observed by the view (Fragment/Activity)
It has 1 (ViewEvent) component that is used by the view to trigger changes in the observed components above.
ViewState : It contains your data, like a List, like a boolean that determines if something is enabled, etc...
When there is a change in any state data, like an update to the List, the observer receives everything, and updates everything.
ViewEffect : These are one off "effects" like starting an animation, making a toast. You will update this with new data when you not concerned about the state of the effect. Like I don't care if there is another toast on the screen, atm. Just make a new one with new information, and show it.
ViewEvent : This allows the ViewModel to receive events from the view and start the "update" process. If a button is clicked in the view all the view would do is send a ViewEvent to the ViewModel stating what has been clicked. Then the ViewModel updates the ViewState/ViewEffect based on the ViewEvent received, which then propagates to the view.

viewModel.setTitle(text) is a anti pattern in android?

developing app, I thought whether my viewModel.setTitle(text) is an anti patter or not.
I know the Ideal of a viewmodel is that doesn't know anything about the views.
But the View know the viewmodel.
So I tried that var title = MutableLiveData<String> in viewmodel, and the view set the title text like this viewModel.setTitle(text)
I want to know my using viewmodel.setTitle is an anti pattern or nothing.
I think it will be a great understanding for you. If you're setting on a string on `observable it'll not breaking the pattern. Here is the detailed discussion regarding this topic
So according to my knowledge, lets consider the responsibilities of each layer first
View - Observes data in ViewModel and notifies UI event
ViewModel - Presentation logic
Model - Business logic
So view should be notifying the ui events to ViewModel, in your case view is actually asking the ViewModel to set the title.
So I have a suggestion, are you getting the title from an Intent, if yes then why not pass the bundle directly to ViewModel and let the ViewModel parse the data
viewModel.onCreate(bundle)
Since onCreate is an UI event we can use it in viewModel as well.
In your viewModel.onCreate your ViewModel can set title, fetch some initial data and do what is require to initialise the activity/fragment
If you are getting the title from server/backend i.e dynamic title, than I think your ViewModel can directly handle it
If your title is static and is set directly, then you should ask yourself is there a good reason to pass the title to your viewModel and set it from there, does it benefits you or is just creating boilerplate. If you are using it from strings.xml you can change it directly from strings file
So to answer your question is it an anti pattern, according to me yes. Why? instead of notifying UI event to viewModel, view is actually passing data to viewModel

MutableLiveData<ArrayList<T>> vs MutableLiveData<List<T>>. Why should we use List here?

I created a library here: https://github.com/chanjungkim/ALiveData
This library is made because of MutableLiveData<ArrayList<T>>. Many people who learns about LiveData complains or they are confused with this type when they need to manipulate(add, remove, etc) the MutableLiveData. That's because ArrayList is easy to manipulate and _arrayList.value!!.add(item) or _arrayList.value!!.remove(0) seems to notify. But they don't.
At the end, when we want to notify, we must assign a value like _arrayList.value!! = mList. ArrayList and List both need to set the data like _arrayList.value!! = mArrayList or _arrayList.value!! = mList.
My question is List doesn't have add(), remove(), etc. On the other hand, ArrayList already has those functions and helps us manipulate the list much easier.
some people suggested like this
_list.value = list.value.toMutableList().doWhatever().toList()
So, what's the point of using List over ArrayList? Could you give me example with the explanation of using it?
LiveData can be used in different ways, and of course there is no one correct way, but a very common way of using it is within the Android MVVM architecture recommended by Google for use in Android apps.
In this architecture, the Activity (or Fragment) observe the LiveData of the ViewModel. When doing this, the goal would be to make the UI as 'dumb' as possible, where you try to handle as much of the app logic and behaviour in the ViewModel, and the Activity simply observes and reflects it on the UI.
In a case like this, it is often preferable for the values of the LiveData being observed to be immutable.
By doing this, it limits the Activity from being able to manipulate the data it is observing, such as add()ing or remove()ing anything from it. As just described, the goal should be to limit the UI's ability to make exactly these type of changes. If the Activity wants to add() an item to an ArrayList that it is observing, it should instead do this by calling a method on the ViewModel, which will in turn update it's own LiveData.value to the new, updated list, which will in turn be observed by the Activity and updated on the UI.
By only allowing the Activity to observe the immutable values, it helps enforce this separation of concerns, and limits any accidental 'leak' of logic into the Activity itself.
This idea can be extended further by ensuring that the observed values are of type LiveData, and not MutableLiveData. Using the latter can allow the Activity to manipulate the live data on its own, and break the MVVM pattern.
A List is an interface, and defines the methods that must be implemented by any classes that would like to behave like a list. It can be considered the 'most basic' version of a list, and only defines the minimum requirements for an implementing class to behave like a list.
In the same way, the List interface itself extends the Collections interface, which in turn extends the Iterable interface. Each one adds more functionality to the one before it... kind of like lego blocks stacked on top of each other, creating more complex shapes.
An ArrayList is a class, which implements MutableList (which itself implements List). This means that an ArrayList can be instantiated, and passed around as an actual object. Because of this object oriented design, and according to the Liskov substitution principle, any class (or interface) can be replaced by a subclass (or class implementing the interface) interchangeably.
This is a fundamental principle to object oriented design. It helps break parts of the application down into smaller, more basic and more manageable pieces, and then grow as required.
To answer your question more specifically, if the class that is observing the LiveData only cares about the methods defined in the List interface, then that is the all it requires to know about the value. The actual value could in fact be an ArrayList, a MutableList or even a custom class MyOwnFancyList<E>: List<E>, it does not matter to the observer, just as long as it implements the List interface.

Two-way binding with RxJava on Android

Recently I've been developing some functionality and it seems to me that it would be nicely modeled with some form of two-way binding.
Example: there's a screen where user can fill some forms and save some content. Later user can come back to that content and edit it. Content is stored in a DB so the content should be fetched asynchronously. I use RxJava and Mosby MVP to create MVVM-style connection between the fragment and presenter.
The problem is that forms should be validated on the fly, so any time some part of the View changes Presenter should be notified. But when asynchronous content from DB arrives (in case user is editing existing content) view can corrupt 'initial' state from DB because of the transition between the states. Also there's a risk of infinite event passing cycle between view and presenter (distinctUnitChanged() doesn't always help with this, because state can alter like 1-2-1-2-1)
I've found 2 workarounds but I am not satisfied with them because they're rather impure and don't feel like idiomatic FRP.
The first one is changing a view in the way that it doesn't send events until it received the first state from presenter.
The second one requires sacrificing Presenter purity. Presenting is setting a flag which tells if we should accept view's state change. It will skip events from view until it will receive the one it passed to the view (initial state).
Things are getting even harder because in Android view can disconnect and reconnect to the Presenter at any time (with or without saved state) and Presenter should be the source of truth.
If anyone has any examples of two-way binding implementation with RxJava or any ideas I would be grateful.
Consider using swichMap() (instead of flatMap()) when loading asynchronous content from DB as switchMap() unsubscribes from previous input validation while the user changes form.
Probably this solves your problem.
Btw. It seems that Mosby MVI module is better suited as traditional MVP for what you are trying to achieve (RxJava, Two-Way-Binding).

MVC on android: Model change and animation

After some thinking/reading (especially following series) I came to accept the following general rules for implementing MVC:
Model - set of simple dummy Value Objects, responsible for keeping the state. Model classes are Observable and notify Observers - i.e. views when changed. Model code could be android agnostic.
View - classes able to keep/update its visual state - based on android.view.View/ViewGroup family - by inheritance or composition. View classes are Model-aware, they receive update of Model's state and re-draw accordingly. All user-input listening code is delegated to Controller.
Controller - all user-input processing code in your activity/fragments. Controller updates the Model, which in turn, will trigger subscribed View update.
Sounds simple and certainly doable in most cases.
Now, consider for example:
Controller/Activity keeps track of 2 Model objects model1 and model2 and changes them based on some application logic.
View receives updates from objects model1 and model2 independently as per design above.
Now, suppose the View wants to show animation based on mutual transition of both model1 and model2 for which it needs to know changes of both objects at one time, or as a single event.
What would be recommended way of doing it, keeping mvc design above in place?
I thought about options:
Have a "SmartModel" which encapsulates both model1 and model2, make the mutual changes/transition and inform the View. I don't like this approach because Model becomes not really just "dumb" state representation, but also drags some application logic from Controller.
Have Controller inform the View about the changes it did on both model1 and model2. In that case neither model1 nor model2 need to implement ability to notify the View, i.e. there is no link between Model->View anymore.
May be there is much better option / I am missing something.
Any insightful suggestions will be highly appreciated.
I think the option 2) is similiar with MVP pattern, controller is kind of presenter to change the view for model.
Model View Controller, Model View Presenter, and Model View ViewModel Design Patterns
If you want to follow the strict MVC way, maybe you need to fire some change event to notify the View observers, so they can know what and how exactly the model changes, so they can do partial refresh and animation.

Categories

Resources