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.
Related
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 write android app using MVP pattern. My question is regarding database layer. I want to make it maximally independent, so it will be possible to replace it with something else without code changing in Presenter in the future. I decided to use pure SQLite without ORM, since the user table is updated in different places with differenet fields (in some place I update user's name, in other place in code - token etc.). ORM (I used realm) doesn't allow to do it, you have to write separate method for updating name, separate - for token etc.
Another problem is with ContentValues: when you update user you have to specify the fields you want to change via ContentValues in Presenter, and then Presenter calls repository.updateUserLocal(contentValues), so my Presenter dependents on data layer (if I decided to add ORM to the project, I will need to go to every Presenter and remove ContentValues). So the architecture is bad. Can you please advice how to organize the architecture of the app in the best way?
I am working on an android app with some networking aspects. There are places in the app that, when a button is pressed, a call is made to a server with a response full of data coming back. My question is regarding creating a robust flow where i have my network calls separated in their own class and all i do is instantiate a networking object such as new MyNetworkHelper(accessClientServer) and give it the name of a client server. This object would then instantiate the appropriate object (ClientServer or StudentServer or TeacherSever etc) to do with accessing that server and doing any database saving and returning a response to the MyNetworkHelper object which would return to the button that was pressed.
Is this the best way to do this kind of task?
What you propose is not unreasonable but could be more standardized using standard patterns such as your helper being a Singleton (and your additional servers as well if they are intended to be used in such a fashion). I would recommend you pick up a beginner book in Design Patterns and Architecture.
In my app I need a central storage object that will be accessed from different parts of the application (like a singleton data holder).
AFAIK the clean way to implement singletons in Android is to use the ApplicationContext.
How can I
put data (like instance of List<MyPieceOfInformation>) in the ApplicationContext and
get them out of it
?
Is it correct that the only way to store more or less complex data in Android is to use the built-in SQLite database?
you can use mysql and others as well.
it is all depends if you want to save the data in local or external.
as external, for example, you can use mysql and web server, then communicate using json.
for saving List, you can use static.
In my app I need a central storage object that will be accessed from different parts of the application (like a singleton data holder).
Then use a singleton.
AFAIK the clean way to implement singletons in Android is to use the ApplicationContext.
First, there is nothing in Android named ApplicationContext. You probably mean Application.
Second, in the opinion of many experts (myself included), a custom Application is less "clean" than regular singletons.
Is it correct that the only way to store more or less complex data in Android is to use the built-in SQLite database?
Comparing a singleton to a database is like comparing an apple and an asteroid, on the grounds that both are made of matter and, in English, begin with the letter "a".
A database is persistent. You use a database when you want to save data persistently.
A singleton is not persistent. You use a singleton for transient data, such as a cache of data that is backed by a database.
I'm in the process of implementing my first ContentProvider. Since I'm quite inexperienced I wanted to check if my general design is sound.
So these are my requirements:
The web-service providing the original data might update the data it holds once per day. I can check for such a version change.
From the app's point of view, the data is read-only (think of weather or stocks data).
I already have a class that can take queries from the application domain, transform them into matching HTTP requests and asynchronously return domain objects. As you might guess, this is what the app currently uses to obtain data directly from an activity.
Now I want to do better and employ a ContentProvider to persist data locally.
Once per day the app would start a Service, that checks the data version on the server and when needed, update the data contained in the ContentProvider.
The following is the design that I've come up with:
Arrows indicate data-flow, not code-dependency.
I've noticed, I forgot to add a layer on top of the ContentProvider to convert Cursors to domain objects, but ignoring these details, do you think, this is a sound way of adding a ContentProvider to an app's architecture?
Any advice is greatly appreciated!