I'm building an app using MVP and I'm using a repository pattern.
I have a local data source, which is a DB where I store certain information.
I have a remote data source, in which using Retrofit, I make an API request. This request has a #Query, and that is a String that is stored in the SharedPreferences.
I thought of adding the SharedPreferences to the Repository, as a data source, but since the remote data source should make use of these SharedPreferences -which would be a different data source than the remote- I don't see this architecture so clear anymore.
Thanks a lot for the help in advance.
I think many people over complicate the idea of repositories. The Repository pattern is really just a specific type of the Facade pattern. It is just an abstraction layer which sits between the true data sources (Models) and the consumers.
Let's say we have a system that deals with weather data. In this case I see nothing wrong with having three Modal classes:
WeatherHttp
WeatherDb
WeatherPrefs
These can all be members of your repository class injected through the constructor. All three of these are hidden from the consumers (UI) behind a single repository class:
WeatherRepository
which might have a single public method:
public void getWeatherForecasts(Callback<List<Forecast> forecastCallback);
or Rx:
public Observable<List<Forecast>> getWeatherForecasts();
Behind the scenes of that method you might well make an http call to fetch the latest data, a database call to save the majority of the details and a shared prefs edit to save the timestamp of the last time the data was fetched. The idea is you are free to change the implementation at any time and the consumers don't care.
The single most important thing about implementing a repository is you must not leak the implementation details. No network classes, database DAOs or SharedPreference keys should be exposed by the public API of the repository.
Related
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.
In MVVM Architechture M stands for Model which holds data. as per many references it looks same as POJO classes.
Am i right ?
if yes then whole android life cycle architecture is depend/composed of POJO classes, as with MVVM we can use databinding which also use POJO class or DATA class.
In android room integration it also uses POJO to create table,
in live model architecture most of the people uses POJO classes.
As far according to my knowledge, POJO is not suitable if your app has lot of Api integration as well as if the back end has no SQL which happens in my case,
as Api is not consistence and data happens to be change rapidly and everyday new parameters are added.
Please provide me in short Advantages and disadvantages of using POJO class
and a way to use POJO with non consistence API structure.
Currently i am using GSON for manually deserialization of data.
In summary, yes. Your model classes are simple pojos.
Your UI (your View) can get it's data from the ViewModel. The ViewModel provides this data with data from Models.
But you can still dynamically update the Model in the ViewModel. In the Guide to app architecture, you can find a diagram which shows a common pattern. Your ViewModel gets its Models from a Repository class.
The Repository class handles calls to the database or a web service or any other interface to provide up-to-date data to the ViewModel. The ViewModel doesn't care where the data comes from.
This has benefits in unit testing, since you only need to override the Repository interface if you want to provide mock data to your ViewModel.
Source: Google, https://developer.android.com/jetpack/docs/guide
I'm brushing on my Android dev skills and have been playing around with the Architecture Components. So I created an entity class using Room annotations for persistence to the database and implemented Parcelable on the entity class partly for the purpose of putting the entity object into an Intent object and passing it between activities/fragments. I just want to know if this is a good practice. Are there any cons of using such approaches such as database leaks or security flaws? Just curious.
I just want to know if this is a good practice.
IMHO, in modern Android app development, no, for a few reasons, including:
Repository pattern: The current pattern in Android app architecture is to isolate data storage and transfer concerns into a "repository" object. The repository knows the details of where the data is coming from and going to (Room, Realm, Retrofit, etc.). The rest of the app neither knows nor cares, as the rest of the app just talks to the repository. With this pattern, you would pass identifiers around between activities and fragments, and the repository would hand over model objects based on those identifiers.
Hide implementation details: Your UI should work with an ideal set of model classes, ones that are not tied to particular implementations of data storage or transfer. That way, should you elect to change your implementation (e.g., from Room to Realm), your changes remain isolated and should have little effect on the UI. If you use a repository, the repository would be responsible for converting from Room entities and Retrofit responses into standardized model objects that the rest of the app knows how to use.
Single source of truth: Once you start passing objects around via Intent extras, you are making copies. If one part of your app then wishes to modify that model object... how will the rest of the app, holding other copies of the data, know about those changes? Ideally, you have a repository with a reactive API, where the repository is the party that makes the data changes. It can then notify other interested parties about the data changes, delivering an up-to-date rendition of the model object.
IPC memory limits: Every time you use an Intent with startActivity(), startActivityForResult(), setResult(), etc., the contents of that Intent are passed to a core OS process... even if the activity being started is in the same process as the code that is requesting that activity be started. There are memory limits for how big an Intent can be (roughly speaking, 1MB or lower). Passing full model objects around may work fine right now, but later if somebody adds a Bitmap field or something to the model, you can get in trouble.
I am currently trying to wrap my head around the architecture components of the android platform, according to the official guide:
In my app I currently need to store a list of strings (names) and access it in multiple places (activities as well as services). 2 possible approaches come to my mind:
1) store them comma-separated in the shared preferences.
2) create an entity and room-table with the name as only column.
I would prefer the first approach since I only need the names as one single string to perform a contains()-operation. using a room database seems to be more of a hassle for this purpose.
My concrete Question is: is it okay to store the appcontext in the repository-class (which is a singleton) or am I breaking any conventions/architectural rules? Or would it be better to actually use room for this?
If you want to use the component architecture, and your repository needs to communicate with data sources that need a context, like room or SharedPreferences .. you'll need to extend your ViewModel from AndroidViewModel that will provide you a context that you can pass to your repository to use it to access the Room database or the SharedPreferences. there is no problem using a context in the repository, even if it is singleton, you already need it to access Room.
For android MVVM architecture, in all the examples that I have seen, people either use Room to store/retrieve data or they get data directly from API calls through the Repository class.
I'm neither doing an API call nor using I have Room database to store data. But I need my ViewModel to get the data from the repository and pass it to my Actvity.
Can your Repository class inherit from Application class so that you can save static variables/companion objects if you don't intend to use Room for saving data locally ?
What is a good way to handle this case?
In general, in Software Engineering a Repository is used to abstract the Data Layer (Database, Web Service) from the rest of the application (usually directly Business Tier), a good example would be this schema of a booking website:
It receives the updates via the Publish/Subscribe asynchronous connection and sends them to the other components. So the components are independent of each other.
So Repository is just a simple mediator class that is used to make the application more modular, so that you can swap out pieces easier, and make sure that the rest of the app doesn't bother with DB connections or HTTP calls and so on. So technically, you can inherit from Application (or anything else) and use it to save static variables and so on.
But as explained here:
The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
So it's entirely up to you, you can use the repository style as you wish, it's not at all tied to Room or anything else.