Android MVP communications - android

I'm very new to MVP and can't seem to grasp this concept.
Basically I have an activity which has an onClick which displays a DialogFragment. The activity does what it needs to do with MVP. The DialogFragment does too. However they are fully independent with regards to linking to each other which is posing a problem for me. When the DialogFragment chain is finished doing what it needs to do, the presenter on this layer holds the data to update the view on the Activity layer. I want the presenter in the DialogFragment layer to give the data to the presenter in the Activity layer who can easily let their view know as it's already linked up nicely.
I've thought of interfaces, read about eventBus (I know nothing about this so be kind).
There must be a specific way of achieving this because it must be a common task, I know I'm going to be doing it a few times in this application.

Your model is the data source in MVP.
Don't know if I got your case properly or not but the model is responsible for providing data to the presenters.
So generally, your other presenter should be accessing the data it needs from the model. Your first presenter can ask the model to do insertions or updations etc required as per the business logic.
Once the alterations have been done by the model, your second presenter can access the data by asking for it from the model.
Hope, I made that out clearly.

Related

Discuss using Kotlin Coroutines with MVVM?

I am using Kotlin Corountines with MVVM pattern and faced a problem: The data processing part is being done inside the ViewModel. While the repository seems not really necessary. When the application needs to call many APIs, the ViewModel will swell. What is everyone's solution to this problem? Thank you
The repository is needed, because in the case when you have a large app and gave too much responsibility to the ViewModel it's broke the separation of concerns principle.
Basically in the Andorids Guide to app architecture :
A first idea for implementing the ViewModel might involve directly
calling the Webservice to fetch the data and assign this data to our
LiveData object. This design works, but by using it, our app becomes
more and more difficult to maintain as it grows. It gives too much
responsibility to the UserProfileViewModel class, which violates the
separation of concerns principle. Additionally, the scope of a
ViewModel is tied to an Activity or Fragment lifecycle, which means
that the data from the Webservice is lost when the associated UI
object's lifecycle ends. This behavior creates an undesirable user
experience.
Instead, our ViewModel delegates the data-fetching process to a new
module, a repository.
And direct answer for your question:
Even though the repository module looks unnecessary, it serves an
important purpose: it abstracts the data sources from the rest of the
app. Now, our UserProfileViewModel doesn't know how the data is
fetched, so we can provide the view model with data obtained from
several different data-fetching implementations.
Basically, you can give all work to your ViewModel, but it's not recommended.
If you work/planning to work as a dev, maintaining your code, make it flexible to change and understandable for others is also important and usually, everyone appreciates this

In MVVM, is the ViewModel always necessary?

I'm new to making android apps, Kotlin, and just trying to get my head around the MVVM design pattern.
I'm attempting to make a login screen while also integrating well with my team's existing code. Making the login screen work went well until I noticed that I was running into life-cycle issues with uninitialized lateinit vars (even though the code definitely ran the initialization statements) like SharedPreferences or the username and password fields etc.
After reading up more on MVVM, I believe that the existing code which I was learning from (which contains lateinit vars for Context, the Fragment, and View within the ViewModel etc) is fundamentally flawed and fails to decouple the ViewModel from the View life-cycle.
However this has me confused. To my understanding, the ViewModel is supposed to contain the business logic and any data which we want to survive configuration changes. On the other hand, the LoginFragment should only contain UI and OS interactions such as displaying the View or capturing input.
The LoginViewModel only contains code interfacing between the elements of fragment_login.xml and SharedPreferences, or logging errors:
resetFields(): empties the fields to blank
onLoginButtonClicked(): just calls the Retrofit function to POST the username/password a server for authentication
onLoginSuccessful(): saves the data to SharedPreferences
onLoginUnsuccessful(): changes the field's error message and logs the error
Because I used DataBinding on the xml elements, nothing (as far as I can tell) needs to be independent of the life-cycle (or rather, several things require access to the context or fragment!).
What is the proper way to go about this? Currently I am thinking that the ViewModel simply shouldn't exist and that all functionality (of which there is very little) should actually just be within LoginFragment). I was considering learning about and using LiveData next, but I just can't see how LiveData or ViewModel are necessary in this situation.
The main goal of any architectural pattern is to achieve Decoupling, Single responsibility and restricting Anti Patterns, to be precise code should be more readable, scalable and easily testable.
I know in some instances using this patterns might seem redundant for your use case, but always keep scaling in mind when ever developing even a simple feature. This will pay off in long term and help peers understand and isolate code better.
In Android, always remember view or UI(Activity/Fragment) should be as dumb as possible, only responsibility of them should be to listen to user touches and display data, by doing so you can test all your logic in isolation without relying on Android Framework.
MVVM is once such pattern designed keeping pain points of Android in mind, it does not cause any harm using it when needed to delegate even simple tasks like storing data to preferences, minor transformations to data before displaying. Let's say you have a static page which just displays static data using String and nothing else then you can avoid ViewModels.
MVVM pattern does not enforce you to use ViewModel for every Fragment/Activity, it recommends using it when needed as a best practice, ViewModel is just a data holder which persists configuration changes.

Clean architecture. What are the jobs of presenter?

I have been reading some articles about the clean architecture, and how it can be implemented in android. I saw the sample app which shows its Android Implementation. Also, I went through a nice talk on Clean architecture on Android
So, I kind of understand most of the concepts, but there is some clarity that I would like to get on certain things.
As per my Understanding,
The View layer is the outer layer which deals with the UI, and
framework related stuff
The presenter is the direct communicator for the view, which accepts user inputs, and executes certain use cases based on this by passing it to the use case layer or the interactor layer.
Interactor executes the use-case, give it back to the callback sent by presenter,
Presenter again converts this result into a view understandable data structure (a ViewModel) and just pass it back to the view.
I am not listing more details about the inner layers like repository since my question is related to the above-mentioned steps
Here, does the presenter have the only job of acting as a mediator between UseCases and UI, as a data dispatcher?
Does it only do the view model to use case model conversion and vice-versa?
The input validation logics rely on which layer? Can it be inside the presenter? For example, if we take a small use case of a sign-up process,
Once the user entered the details and clicked sign-up button, and data sent to the presenter, is it like
Presenter validates the input values if any error is there notify
the view
If values are proper, convert it to a use case model, and execute
certain use case, and once the result is given by the interactor,
again convert to view model, send it to view.
And the second question is, who controls the navigation? The View or the Presenter or the UseCase?
who decides where to go next?
For example - Consider a use case of a login process, Where user will enter the credentials and click OK.
On successful login,
If users e-mail is not verified, go to email verify screen
If users profile is not completed, set-up the profile then only go to home screen
If user is new, show new offers screen, else directly go to home screen
So, who is responsible for making these decisions on which screen to go next? Is it the presenter, which decides and navigate the view accordingly? Or is it the use case handlers responsibility to inform the presenter what is the next State?
Sorry for making the question too long, but I just wanted to elaborate my current understandings. Thanks in advance
Here, does the presenter have the only job of acting as a mediator
between UseCases and UI, as a data dispatcher?
Yes
The input validation logics rely on which layer? Can it be inside the
presenter?
validation should rely on business layer not the presentation, can it be inside the presenter? sure it could, but what if you have multiple screens that take similar inputs, do you have to repeat your validation logic inside each presenter! you can argue that you can make a base presenter, but it's not the perfect solution, because presenter should have one purpose.
And the second question is, who controls the navigation? The View or
the Presenter or the UseCase?
do you consider the navigation is part of the Domain or the presentation or the data layer, it's likely related to the presentation layer, but you could make a small component inside the presentation layer which is control the whole navigation generically, So you can use this component the moment you decide that you do need other platform and throw your activities away. you can find this approach in the sample you've mentioned.
EDIT:0
How you pass data between modules where they have different models?
you simply use mappers, and the reason is to make each module has its own models or entities, so it would be easy to test each module separately.
About presenter and view, let's say you want show error message, presenter decides why it would be shown, view decides how it would be shown.
I think the problem in understanding the clean code presentation layer with Android, that Activities and fragments aren't only view, they're also The process and the lifecycle which your code would be live in, clean code came along to separate spaghetti code on those Activities and fragments.
EDIT:1
adding to the last point, it's clear now that Google and the support team there made a great effort to make Activities and Fragments dummy views as possible via introducing the great set of libraries "Architecture components". I encourage anyone to check them out, even if you're using MVP, you'll find a great benefits.

What role an Android Service should play in the MVP pattern?

I am developing an Android app that does Human Activity Recognition.
It basically works like that - Service constantly reads the accelerator data and stores the recognized activity (i.e. Walking, running) in a database. The user can see all of the recognized activities in an ListView in activity (accesses the database). Every User table in the database has a pa_goal (physical activity goal) field which the Service reads from the database and does some checks.
The user, of course, can change this goal from an activity. Since I will be implementing the MVP architectural pattern.
I am unsure where to put the Service? It surely isn't View. Any advice?
In a clean architecture, which is what I am assuming you are using MVP for, there is the idea of separating the framework from the business logic. This is essentially what a normal presenter allows you to do.
In this case its not a view you are dealing with but the principle is similar. You don't want all your business or application logic mixed in the Android code when you can separate them out for nicer, more single responsibility classes. So I would say that while it isn't a view you should still have a presenter type class (probably better to be called controller or manager maybe).
This class would be a POJO that controls how your service behaves which is easily testable with standard junit tests and service mocks. This class and the service could then be put into its own feature package and interact with the back end models the same way as your presenters.
So, in summary, the role is of another feature of your app that sites alongside the other features (which are usually just views in my experience).
Hope that helps
This article helped me in a similar situation, although may not be exactly yours, the idea is the same:
https://android.jlelse.eu/android-bound-services-and-mvp-12ca9f70c7c7
Basically, the author works around the fact that a bound service is tightly coupled to an activity, and it adds extra lifecycle calls to it.
I am in the same situation. Finally I decided to do something like this:
Activities or Fragments are out of scope, they do not know anything about MVP BUT i am going to use an event bus like Otto to send signals/events, So:
My classes which extends some kind of Presenter know nothing about Android Context but they will have an MvpView interface, with only onAttachPresenter and onDetachPresenter.
The class which extends Service will have a Presenter attribute and implements some MvpView interface with onSucess, onError, onStart, onComplete or something like that and same events for Otto (onSucessEvent, onErrorEvent, onStartEvent, onCompleteEvent).
So when I need to do something the Activity or Fragment will start the service, the service will "start" or talk with the Presenter and when the presenter finish with success will call to mvpView.onSuccess() and store the info inside a local DB with SQLite (storeIO maybe) and finally the Service will invoke Otto and pass the signal (without any data on it), probably onComplete.
Finally the signal will be catched by my UI (fragment maybe) and retrieve all the info inside a DB in SQLite.
So when the onSucess happens the UI will show the latest and best data BUT when onError happens will (at least) show some info (or not if you want) saying to the user "there was a problem but at least you can see something", bot onSuccess and onError will call onComplete after all.
Do not know if this is the best solution but in this case I think I am not going to deal with Activities or Fragments lifecycle and do not care about onSaveInstance and restore data when the user rotates the device. It will always fetch the latest data inside DB, and if something happens (no internet connection) you can at least show something when you receive the onComplete Signal.
Some facts I am still thinking:
The Presenter won't be a singleton class
Presenter knows nothing about Context but yes with MyApplication class
What happens if for one screen (Fragment) you have differents service with differents onSuccessEvents? Simply use some kind of action as an ID, to identify them.
Never make the Activity Fragment implements the MvpView, you will have to deal with the lifecycle.

MVP pattern Android duplicated methods in presenters

I have a couple activities, while each of them is rather unique, there has to be some common api calls like getCurrentUser() or updateUser()
Given the MVP pattern (I am currently using MVP mosby), since each of these activity only has a single presenter. As i am developing, it seems that sometimes I copy-paste a lot of these common api calls all over these presenters. Say I have api Call A, B, C, D.
A, C are used in presenter 1,
B, D, A are used in presenter 2,
C, E are used in presenter 3
.....
and so on. It is really difficult to find a "common" presenter to inherit from. So the api calls, C and A are basically copy pasted.
My question is, given the current situation, what is the best way to avoid code copy-pasting? Is it almost not avoidable? Or should I try my best to do OOP but risking a bunch of refactoring every time API calls are added/removed from different presenters?
Interactor pattern (use case pattern) can solve your current issue of duplicating code.
The idea is that you extract all logic behind getCurrentUser() and updateUser() methods into a class (interactor) and use this interactor inside multiple presenters.
This is a very simplified explanation. I suggest you do more research starting with this post and this post for example.
You should decouple your common API and presenter code by putting all the API calls inside one or multiple Java classes that can be referenced from any presenter.
Therefore.
ServiceA exists (A Java Class).
ServiceA performs API calls A,B,C,D.
Service A can be called from Presenter1, Presenter2, PresenterN, PresenterN+1.
It should not matter what the presenter is.
If you want to restrict certain Presenters from having access to different API calls. Then this is when you should consider having ServiceA, ServiceB, ServiceC. Where ServiceA can only make API call A and D, Service B and Service C behave similarly.
Decoupling your Presenter code and common(Web Service, internal API, w/e code) will allow you to scale without having to do copy and paste.
Good luck.
I think you are risking more refactoring if you don't do it the OOP style, with inheritance.
Let's say you want to modify the way you handle some api call. If you are copying code, you'll have to refactor everywhere you copied the code in the first place. If you inherit from a common presenter, you can just modify once.
You should make interface for your API that contains all your API requests. Then make singleton class that execute these requests, and you can easily access this class from your presenters.
Now you will still have some duplication and you will need to call this singleton multiple times in presenter and handle response in each of them, but that's what you need to do. Every presenter should be able to handle response different way, so you can't just pack them as one (even they will usually handle it the same way - by passing data to view).
If you think that you are writing a lot of similar code that does nothing, well that what you get with MVP. You also get great testing ability, easier refactoring and easy mock of requests - you could swap your real singleton for mock that implements same interface and everything works.

Categories

Resources