I don't understand few things about repository in mvvm, also have seen multiple blogs and code templates. Every one of them doesn't match with other. So
Why there is needs to have multiple Repositories classes? Why single repository shouldn't handle all the data IN OUT for the app?
Why Repository shouldn't be a SINGLETON class in project?
What a repository('s method) should provide to viewmodel Result(Sealed class) or actual response from a api like list(or error)?
SharedPrefrences should be handled by Repository as well or not? if no why
I believe Repository should be that part of your code which should process all the data from multiple source whether be database or network or sharedprefs. So what do you think?
Purpose of repository is not only to manage requests/response but also provide a layer to keep responsibilities separated. If you have 2 modules (let's say Login and Registration), it is much better to keep repositories separated to keep things clean and simple rather than having a single repo with spaghetti code.
This point is opinionated. IMO you can have singleton repositories because they are stateless i.e they do not hold any kind of data which may cause conflict between multiple ViewModels/Modules.
Depends on you but it is much better to return Result. With Result you can handle Success Failure and Error Messages easily and return different Error Messages directly from repository rather than deciding in ViewModel what message to show. Messages can be either from server or internal exception messages.
SharedPreferences is a datasource. Yes you can manage preferences using repository pattern.
Related
I have been studying and trying to implement the clean architecture in Android and have been working on a simple project to get some practice in.
The app simply shows popular movies, tv shows, and actors. The information that I would like to display about an actor must come from two separate calls to the API. My current design is a CharacterRepository that depends on Remote, Local, and Cache Datasources. In the other repositories for movies and tv shows, the NetworkDataSource simply delegates to a single operation of the related API service class.
What I'm asking is should the character data source expose two operations (getCharacters, getCharacterDetails) and leave the combination of data as a responsibility of the repository, or should it expose a single getCharacters operation that merges the data from the 2 API calls into a single object?
From the official Guide to App Architecture
"The repository is the only class that depends on multiple other classes; in this example, the repository depends on a persistent data model and a remote backend data source."
If your data comes from multiple sources like local, remote & cache. They should be combined in the repository.
But, If you have 2 APIs one to fetch the list of characters & another one to get details of each character, they can be combined in the data source as both are the remote sources.
I have difficulties knowing how to structure the classes in an MVP Android project that uses retrofit2 for calls to the API. I need to make a login and a registration. The requests for both of these are different but the response is the same. How can I create&structure the model classes in the best way?
As the matter of fact in MVP design pattern, there is a View(mostly a fragment), a presenter (has a duty to do logical things) and we have no an actual model there!
instead, there is a data part of your application that contains your database and internet connection that we can call it model.
I searched all the internet but I found the best example in below link:
https://github.com/googlesamples/android-architecture/tree/todo-mvp/
I am following clean architecture, and I understand the use of the repository for actions like getUsers or queryUsers. However does not make sense to me the use of a repository to login a user. How should I communicate with the Data Layer then, should I skip the repository layer and access the network layer?
I definitely think that you should not skip layers.
The whole point of introducing a certain architecture is to follow it without exception, so all your app modules behave in an expected and predictable way.
So, if you look at it from a different angle, what does logging in mean? You get a username and a password and you must check if they match a username and a password that are stored in your datasource. To do this, you run a query against your current users. And queries are run where - in the repository! You said it yourself - the repository is where all querying should happen. What is implementation behind it is of no importance.
So, my suggestion is to add a method like this one:
public interface UserRepository {
User findByUsernameAndPassword(#NonNull String username, #NonNull String
password);
}
If you manage to find a user - good, he's authenticated, if not - sorry, try again.
from this guid i think using repository is a better choice. my answer based on the definition of the repository quoting :
Repository modules are responsible for handling data operations.
I believe in clean architecture you should not skip layers. I see a few options here:
userRepository.get\set-User() - for me, it looks a bit weird because Repository is an abstraction over collection while we need only one.
create an abstraction over user storage. For example, userStorage.get\set-User() or userStorage.login(User), logout(), get()
I am following MVVM architecture for my app. In Activity I need to getNews() from a URL, if news is not already cached.
Activity will ask ViewModel to give the News Json and ViewModel will look into the repository, and decide to send data from local or remote repository.
Now the confusion stems from the following point: Should I create a separate Repository class for each Activity, or a general Repository class for the entire project with which each activity communicates. The repository class would be huge in the second approach.
I am unable to find out any official guideline on this topic, and I would like to know the best practice on this regard.
Creating a single repository for the whole app is definitely not a good idea, since that will become very large and completely unmanagable very fast.
I would suggest that you create separate repositories for every viewmodel and additionally services for data that is used by multiple viewmodels.
In your example that would mean that you have a NewsSource service that takes care of retrieving and caching the news JSON and have all your repositories that need that data retrieve it from there.
I'm developing project following MVP architecture. Usually, when I use recyclerView, my presenter controls Adapter data. But now I need to make recycler adapter with data from cache (or something like cache), recycler's size dosen't depends on cache size, so I make cache via HashMap where the key is - position of recycler, if there is an item in map then the data shows, else empty row with something like "add events" btn. And I can't realize where the place for that cache in such structure - Model (Dao or something like CacheManager) or in Adapter.
The cache idea is following: I have some types of events which store in database, every event modifying changes it in db - so the cache has to be updated either.
The main questions are: where to keep this cache and load it to adapter, how can i keep it sync with database changes.
P.S. Also I tries to use RX, so if it can be solved with it - would be very interesting to try.
P.P.S If it the Repository pattern is the way to solve - welcome. Read about it sometime ago.
Your problem doesn't sound like it's related to RecyclerView.Adapter -- and actually you shouldn't try to solve it within your Adapter: the responsibility of the adapter is to act as a bridge (or "adapter" ;-) ) between your data and view component. Giving it more responsibility would turn it into something that is not interchangeable with other Adapter implementations (you don't want this!).
You should probably find a clean way to abstract your data persistence. The in-memory cache should go into that abstraction. You mentioned the repository pattern, this would be good choice IMHO.
Your architecture should roughly look like this:
adapter -> repository -> |-> cache
|-> database
The repository combines the logic for data access (your DAO) and the cache handling (your CacheManager). The repository would always first check the cache and then fetch data from the database. It also updates the cache if non-cached data is fetched. Furthermore, it registers for updates on the database. As soon as the database notifies for changed data, the repository has the chance to update the cache and/or propagate the notification to the view. The important part is that the interface of the repository hides all this logic; it only offers access to data.
You then need to find a way to make your adapter work with your repository. I'd suggest Android's Loader mechanics. By this you get asynchronous loading and correct lifecycle handling for free. Also this nicely decouples adapter and repository.
If you need some inspirations on how to apply the repository pattern, have a look into the googlesamples/android-architecture Github. The Clean Architecture branch could be a good fit for you.
On a side note: try to find real (unique) keys of your data. Using the position within the data list is usually a bad idea and depending on the structure of your data will result in strange side effects in the view.
I think it's an architecture subject. Rx is out of subject. For example for a repository, Rx is just a way to implement it, and by extension, its cache.
A Google repository provide some samples of architecture. One of them contains an example of architecture with a basic mvp, and a repository who manage cache :
googlesamples/android-architecture/todo-mvp
Another example in the same repository with Rx :
googlesamples/android-architecture/todo-mvp-rxjava
We can be seen here that these two examples share the same scheme of architecture :