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.
Related
I been look into a lot of resource about Android MVP. From what I understand Model is the data access layer that solely deal with any work that relate to access data from the storage (database) of the system internally or externally. For example, external database like Firebase, internal database like Realm, etc.
My uncertainty
I am unsure about the 'SharedPreference' in Android, as it acts like a 'Permanent Session' which store the data within the application,
Does it mean that any data retrieval of SharedPreference Should be done in the Model Layer? or it is okay for me to simply retrieve SharedPreference data in View Layer to being displayed on screen?
Does it mean that any data retrieval of SharedPreference Should be
done in the Model Layer?
Yes
I am working with MVP for about 2 years and here is our team approach: Create a SharedPreferencesManager (Model) class to manage everything that belongs to SharedPreferences because SharedPreferences is a "lite" database (key-value)
It is just an opinion. Hope this help!
Is there a better architecture that we can follow other that making these fields static(bad for performance) or storing in Shared Preference.
Either use Shared prefs or a database. Both are optimized for quick and (more or less) safe access. It might be worth your while to read about Architecture Components, Room (or others such as ObjectBox, Realm, etc) and repository pattern.
Android Jetpack would be your best option. Check out the documentation on Data Binding, it would allow you to access fields like user_id without writing tons of boilerplate java/kotlin code, by injecting the data directly into you xml code. Here's the link: Android Jetpack Data Binding
There is nothing wrong in saving two/three Strings as static variables, In fact it is the fastest way to get repeatedly used variables. I prefer Application class to do so(static variables of Application class), but the issue is if your app happens to crash for some reason, application class is recreated and app starts from the previous activity, alas your static variables are long gone, be aware of this pitfall
Depends on how/when you are using these static elements.
A few application global variables like userSession object might make sense to store in the MyApplication file itself and made exposed throughout the app so you confirm it is valid when app returns from background each time for example.
SharedPreference is not a great place to store secure elements as it is on file storage in unencrypted xml format which rooted phones and others may have access to get to.
Database is a fine option, but it requires more code bloat and requires a database connection and query everytime you want to use the token if you don't plan to store it in RAM.
Another option is a singleton class that is meant to store your necessary application elements like FirebaseHelper for example that could populate into RAM on app startup and utilize your variables throughout the application life.
So really depends on your app needs. You can also use a SecureSharedPreference tool. There are a few open source options out there for this that you can just include in your project that encrypt the xml elements for you if you prefer to use the xml for storing these items.
If it was me, I would either you a secureSharedPref if it was simple things like userId, Token, or things like that that are fairly harmless. Of course it will encrypt them, but worst case if they got your token, they could make a few API calls if they knew what they were doing, unlikely. Now storing things like password, bank info, medical records, or anything else sensitive definitely should be in a Database. In fact, I would go one step further and layer it with SQLCipher.
So long story short is it depends on what you are storing and the risk assessment of it's content being accessed and each app will be different.
Absolutely nothing wrong with storing some static variables or singletons. Anyone building an enterprise level application will have a fair amount of statics in their application if it is architected in a good way.
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.
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?
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.