Android MVP with RxAndroid + Retrofit - android

Recently I started reading a lot about MVP and I want to get into practicing my projects with it.
However I am not able to correctly understand where should Rx + Retrofit code go? I think it should be in Model Layer via Interactors but still can someone share some light on this?
Also what happens with the RX callback? the onNext(), onCompleted() and onFailure() passes data back to Presenter or do we implement listeners and then pass it on to Presenter?
I also want to persist data (Realm/StorIO) when I get it in onNext(), So again pass it to another DataLayer or where should it Go?
Also should we decouple Rx callbacks further?
I am following this post
https://davidguerrerodiaz.wordpress.com/2015/10/13/a-brief-introduction-to-a-cleaner-android-architecture-the-mvp-pattern/
and this seperate github repo from antonioleiva.com
https://github.com/antoniolg/androidmvp

As you pointed the RxJava functionality defines a use case of your model layer so it would be placed in an interactor of this layer. You can create a different interactor for each use case. Let's say you are pulling a list of users from your server, this would be a use case and an interactor that will have the RxJava/Retrofit Observable.
Then you will have a Presenter with an Observer in it which is interested in this users list, so it will be subscribed to that Observable.
And finally when this Observer in has all the data from the Observable (onCompleted), it will transform this data (if needed it) and pass to the View which will be just in charge of display it.

There is awesome post explaining mvp.
Rx is just additional tool for it.
http://hannesdorfmann.com/android/mosby-playbook/
there is deep explanation and source code with example.

Related

Does LiveData have to exist in the Repository?

I'm a beginner studying MVVM design patterns.
Looking at the code of Google CodeLab and other sample codes, a question arose.
As the title suggests, does LiveData necessarily exist in the Repository?
I've been using and observing LiveData in a ViewModel so far.
(There's no special reason, I just used it because I didn't know anything)
By the way, I looked at the code of Google CodeLab to study Room, and I saw that it uses LiveData (or Flow) in the Repository and reference this in LiveData of the ViewModel.
Sample code from other web sites was similar.
But I don't know why LiveData is in the Repository and uses the way it's referenced.
Since LiveData is used in the Repository in the code of official docs such as CodeLab, I am using it accordingly, but I do not know why.
In the MVVM pattern, does LiveData necessarily exist in the Repository? I'd appreciate it if you could explain why.
LiveData is simply an observable data holder. It is lifecycle aware so it is a good practice to use it for providing data to View from ViewModel. LiveData can now be replaced with Flow which have few benefits over LiveData.
From Repository to ViewModel, it is completely up to you whether you want a LiveData/Flow returned or simply return the model that you expect from DAO but still you will require a LiveData/Flow if you want to provide that model to View after receiving that model from Repository to ViewModel.
The MVVM pattern is more about designing software, and organising the architecture into separate layers. The View is the user-facing frontend, the Model is the backend where the data is handled.
The View Model sits between them, converting data from the Model into some form of UI state the View can display, and turning UI events like button presses into calls to the app's backend functions, in the Model.
LiveData and Flow (which are similar - one is Android and one is Kotlin) are ways of exposing data, which is ultimately what the Model does - producing data. Instead of just providing a single value on request, they're able to provide a stream of data.
And the View Model (which is the intermediary between the Model and View - they don't talk to each other) can take that LiveData or Flow, and either expose it directly to the View, or do some processing on it to produce data suitable for the View to display. That way you have a pipeline from the data producer (the Model) to the UI (the View). That's basically how MVVM works in general, this is just using the streaming/producer/reactive model to wire things up and make things like async operations simpler
This is worth a read, it explicitly mentions repositories as the data producer in this model:
https://developer.android.com/kotlin/flow

Can a use case be called in data layer in context of Clean Architecture?

I have read a couple articles about clean architecture concepts here and here and others.
I think I understand what is going on but they didn't solve the question that I have.
I wonder if a use case can be called from data layer. if so, how? if not why?
UPDATE:
what I am trying to do is to track what is happening during each usecase with a event usecase. Sometimes, I need to collect those info in data layer as well.
Let's say I have
CollectEventUseCase
for that event usecase. I want to track if a person data lookup from network was fail but successful from database during the LookupPersonUsecase and I want to collect that information that lookup was failed from network but successful from database, is this a bad idea to call CollectEventUseCase in data layer? is this okay solution to this case? or whatelse should be the right approach?
Short Answer - No, in a CLEAN architecture the data layer should not be calling through to a use case as it would be breaking the separation of concerns. Data layer should only be concerned with data, not business logic which lives in a use case.
Long Answer
One main reason for implementing a CLEAN architecture is for implementing separation of concerns, meaning each layer addresses a specific concern in your app. Expanding on the photo in domain layer Android documentation, an app architecture might look like the picture below.
Where the domain layer would contain all of the business logic for presentation and use cases which can communicate with different sources in the data layer.
The data layer exists to serve as an abstraction over where data is coming from and that should be its only responsibility. Most apps data layers are fetching data from the network and then caching that data in a local database. So to best separate the concerns, a use case should only be concerned about interacting with different sources from the data layer and any business logic.

Android MVVM clean architecture with livedata

I have an architectural question. Currently my app is so simple that user logs in and gets a list of restaurants and he can logout. I use kotlin coroutines for async part, mvvm live data and koin DI.
Here is my login flow when user clicks on login. The regex validation is done in LoginViewModel -
LoginFragment -> LoginViewModel -> AccountUseCase -> AccountRepoImpl -> AccountLocalDataSource or AccountRemoteDataSource
And the response is given all the way back from DataSource to LoginFragment.
I consider the AccountUseCase and AccountRepoInterface as a part of the domain folder along with the AccountModel. The AccountRepoImpl is in repo folder and AccountLocalDataSource and AccountRemoteDataSource is in datasource folder.
My question is ideally the domain should not have any 3rd party dependencies. But my AccountUseCase emits livedata to the viewmodel class and as a result my domain is using android livedata dependency and also it is not doing much but just calling the repo for loginuser. Does it make sense then to have this usecase?
In terms of the LiveData dependency, I would suggest you to ignore it in this case. If you want to make it reactive, either you use library like LiveData or RxJava or have your own implementation. There's no much difference. Just that LiveData happen to be provided by a package that has the word android inside.
Regarding the use case, as you said your app is currently simple. The use case seems redundant for now as the logic is simple in this case but it will be helpful once the app gets more complex.
Some scenarios that I can think of:
when the login logic changes, you only have to update the AccountUseCase which follows the Single Responsibility Pattern (SRP).
when you want to use the AccountUseCase in other ViewModel instead of reusing the whole LoginViewModel.
this makes your code base more consistent, if all the logic are inside the domain layer. Instead of "hiding" some simple logic inside your ViewModel.

In clean MVP, who should handle combining interactors?

I've seen good examples of MVP architecture (here and here). Both present only simple interactors, but I wonder how to deal with more complex use case, consisting of steps, which are repeated in other use cases.
For example, my API requires token to authenticate any call. I've created an interactor to get that token (GetToken). I want to get user's last login date (GetLastLoginDate) and then fetch a list of changes that occured between that date and now (GetVersionChanges).
Where those interactor should be chained? I want to keep them separate, because some of them are reused in other parts of the code. I've came up with two solutions.
Presenter should chain all interactors. This solution works as long the use case is not complex and doesn't have many preconditions. It seems to me it's not the right place, because it burdens presenter with another responsibility.
Interactor can use many repositories (no clean architecture rules are broken then). Why not use TokenRepository in other interactors? Because getting token is much more complex than just reaching to repository. Repeating the steps in other interactor does not reuse already existing code.
Both solutions have their flaws and are against basic principles (DRY, single responsibility principle).
If I were you I would just put the logic of getting a token in a separate interactor (maybe named getTokenInteractor) and call that interactor from your others interactor who may need it.
That way, it would be in an interactor that you chose either to use a token (and call or not your getTokenInteractor) and also in an interactor that you retrieve it and deal with errors.
I would do the same for your "getVersionChanges" use case and let an interactor chain the calls.
Let's imagine you have a presenter who needs to display the version changes. He will call a first interactor (GetVersionChangesInteractor) who will first check if he has a token (by calling getTokenInteractor), then call GetLastLoginDateRepository for retrieving the date, and call GetVersionChangesRepository with that date and finally give the result to your presenter.
That way, your business logic can stay 100% in your interactor and your presenter can focus on how he will display that on screen.
By the way, if your API needs a token for every call you should move it in an Interceptor so you do not have to deal with it at every call.
It's possible that the MVPC pattern is what you're after. This is something I wrote ages ago on it (though the code example is pretty poor so please excuse that!)

Where to put REST API Calls in Uncle Bob's Clean Architecture?

I'm trying to use Uncle Bob's clean architecture in my android app. So, I followed this guy's great implementation based on RxAndroid, Dagger 2 for DI. I know that to get data from data stores (Cloud or local db or disk), the Interactors (Use Case classes in the Domain layer) will invoke Repositories in the DATA Layer.
In my case, I have to execute two parallel REST API calls (Foursquare API and Google places API), then, compare the received data from each call.
Do I have to put these Retrofit calls' implementation in the Data layer or inside the Interactors in the Domain layer ? If any external API call belongs to the data layer, what's exactly the role of interactors in Uncle Bob's approach ?
I'm new to this approach, any help is greatly appreciated!
i think you should call the API in data layer and then process the result in domain layer, of course if the result was independent from any framework.
and interactors was the one that orchestrate the flow of data to and from the entities. (http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/)

Categories

Resources