Room database inefficiency - android

just got started with android room database an I like the efficiency it brings to the android team and the general programming experince. But currently facing some efficiency issues .
my issue is that for a class marked with #database annotation we are recqured to pass all the enties inside the annotation as google explains https://developer.android.com/training/data-storage/room/
#Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
so what if I have like over 50 entity classes and I want to easen the process of passing the classes my Database class is there any option for me ?? I happen to come from a spring background and I like the similarity between the two though in spring there is no such a condition but everything works smoothly

so what if I have like over 50 entity classes and I want to easen the process of passing the classes my Database class is there any option for me ?
Room cannot make assumptions about which RoomDatabase the visible #Entity classes belong to. For example, WorkManager might use Room, and if it does, the WorkManager entities belong to its database, not yours.
You could write some sort of code generator that uses your own personal rules to generate that list of classes, if you wanted.

Related

Is it possible to provide DAOs or Room database without Dagger Module

The Room persistence library defines databases to provide its Daos.
#Database(...)
abstract class DbImpl : RoomDatabase() {
abstract val daoImpl: DaoImpl
}
How could I provide all DAOs in Dagger, without the need to provide these manually with a Module?
#Provides
fun provideDaoImpl(
db: DbImpl,
) = db.daoImpl
You can declare the Room database as a component dependency, thus implicitly provide any declared DAOs from it.
The benefit of this approach is that you save some boilerplate as you don't need the #Provides methods wrapping every DAO. The downside is that the Room database now needs to be created along with your component to link it as a dependency which may incur unnecessary work at app-startup.
I'd stick with the #Provides methods and the boilerplate module. Your DAOs hopefully don't change that much that this would be hard to maintain and it gives you the benefit of being able to create the database lazily when needed. Just make sure that you avoid scoping your DAO wrapper methods, as Room already does some internal double-locking.

How does it work: passing an abstract class as parameter in Room Database builder

I have seen this implementation in Room database.
There is an abstract class AppDatabase -
#Database(entities = {Task.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract TaskDao taskDao();
}
But when you create an Object of this AppDatabase class, you do something like this -
AppDatabase appDatabase =
Room.databaseBuilder(context, AppDatabase.class, "something").build();
My questions are -
How can you pass an Abstract class directly like this without the Override methods defined ?
Like, normally we don't use and pass abstract classes like that, if you do something like this in IDE, it throws an error.
Which design pattern is this and how Room handles this type of things internally ?
1) The idea of using abstract classes is to have a sort of contract between the developer and room. We use abstract classes (or interfaces) because the implementation of those Dao methods will not be provided by us the developers but by Room itself.
2) It is a Builder design pattern, this design pattern is generally used when we have many options for how we'd like to create our final object and the pattern provides a more maintainable api for doing so. The example you provide is just a basic initialization of the database, but we can actually set many params whilst building the database class. For instance we can add the following option when building the database in order to tell it to delete everything and start again in case our database schema changes:
.fallbackToDestructiveMigration()
How Rooms handles thing internally is a bit of a hard question, but in general terms it is an abstraction layer of SQL apis provided by android itself, it will use your contracts (abstract classes or interfaces) for the Daos and the Database in order to create implementations for all of those abstract methods defined in those classes. Once you've setup everything and built your project the first time, Room will generate a bunch of _Impl classes that will implement those abstract methods. For instance, if you have a UserDao, it will generate a UserDao_Impl class that extends (or implements if you've used an interface) the original UserDao and it will provide those implementations. What it does internally will depend on the method, but it's basically using the SQLite api provided by Android.

How to add Dao to Room in runtime?

I am using clean architecture in my app, and due-to module testing I have to keep module logic inside modules. However all examples of constructions of RoomDatabase forcing to keep all DAO's inside RoomDatabase child class.
Is it possible to split RoomDatabase creation and DAO attachment place into two different modules(in case if one of them depends from second)?

Android Realm Project Structure

I started working in a project that already had Realm and the MVVM structure on it. As of now, all Realm methods are static and inside a RealmHelper class, except for some methods that are in the ViewModel classes of it's respective Activity. But RealmHelper class is starting to get bigger and bigger and kinda messy. I wanted to know what are your suggestions to rearrange my methods and classes when using Realm.
It's perfectly fine if you want to keep the RealmHelper class which manages all of the methods that your app can access. You may want to try to convert the methods to one liners that are being directed to another class internally.
So the structure might look something like this:
co.your.app.realmhelper
RealmHelper [public]
WriterHelper [Package Private]
ReaderHelper [Package Private]
So all of your logic is actually happening within the package private classes but the rest of your app would interface with the RealmHelper. The RealmHelper would just manage the instances of the package private classes and determine which methods should be invoked for those classes.
Your other option is to get rid of the RealmHelper in favor of smaller classes. Without knowing what your RealmHelper is actually doing it's difficult to give additional advice.

Using realm for complex objects android

I started using realm. it seemed to work fine, but I have some questions. When I use realm for simple object with primitive fields, everything is ok. But I'm facing issues using it for complex objects.
For example I have a class Passenger. It has several fields
Segment segment;
Documents documents;
....
Each field also has sub objects. Segment class
Flight flight;
Arrival arrival;
int pnrRequest;
So as I understand I will have several tables and I need one-to-many relations to connect this tables. What i want is to store passenger list inside database.
The problem is that I already have this classes as a model, but they dont extend RealmObject. I don't want to have duplicate classes one for model and one for database. Is there a way to avoid duplication of files and conversion from one model to another?
According to documentation it's posible:
An alternative to extending the RealmObject base class is implementing the RealmModel interface and adding the #RealmClass annotation.
Realm requires that all models that should be persisted must extend RealmObject or implement the interface RealmModel (see https://realm.io/docs/java/latest/#realmmodel-interface). If neither of these approaches work for you, you will need to duplicate the class and have conversion methods between them.

Categories

Resources