thebillington
thebillington

Reputation: 1

How to properly manage realm in Android to data bind views, but close all realm instances?

How to properly manage realm in Android to ensure all database instances are eventually closed, but left open long enough for the View to DataBind managed objects and observe changes?

I want to know if there is a best practice when interacting with Realm instances that ensures data can be observed, but also that each reference to the database is properly closed. I have been looking for a good way to solve this issue but so far it seems to be either a major falling point of Realm or a well kept secret. In a previous project I didn't properly close Realm instances when interacting with the database and this eventually led to massive headaches and refactors further down the line.

I'm starting a new project and want to ensure I have everything set up correctly from the get go. The app I'm working on will receive push notifications that will trigger an update from the server and store changes in the Database. I want to observe related data in the Database with Realm so that data bound views can automatically update when the database is changed. Correct me if I'm wrong but is my understanding that to observe the database the Realm instance from which the data was fetched must remain open. This means I can't have a single repository that opens a new Realm instance, fetches the Model I need and then pass it back as I won't be able to observe changes.

The solution I have come up with is to create a repository layer with 3 ways of interacting with the database. The three options will be copy, update and listen. The copy and update functions will open and close a realm instance within a single block, something like this:

public RealmObject copyOrUpdate() {
    Realm realm = Realm.getDefaultInstance()
    try {
         // Transaction
    } finally {
        realm.close()
    }
}

However, I can't use this when I need to observe a model as the database will be closed before the observing View has been destoryed. Therefore to keep track of the realm instance I will open a new instance when I create each ViewModel that requires an observable. Then when I need a managed object I will pass the realm instance in:

public RealmObject observeObject(Realm realm) {
    return // Managed object
}

And finally close the Realm instance when the View is destroyed and the ViewModel is cleared. From my current understanding of Realm I honestly can't think of another or better way to do this and from reading online, I can't find other people with the same or similar issues other than this post which is unanswered:

How to properly separate Realm from the rest of the app?

Any help, insights or advice will be much appreciated so that I can improve my understanding of Realm and avoid headaches further down the line.

I would also like to know the best way to observe a Realm database, as Realm doesn't appear to offer support for LiveData and registering/unregistering RealmChangeListeners seems like an accident waiting to happen. Is there an officially supported way of handling LiveData or do I need to learn to properly use RealmChangeListeners? Finally, I have had a lot of success in the past using Room and feel it is a better solution as it is formally supported as an Android Architecture Component. I see people on both sides of the debate, but is there any specific reasons I should stay away from Room?

Thanks in advance for any help or guidance at all.

Upvotes: 0

Views: 182

Answers (1)

alireza daryani
alireza daryani

Reputation: 835

There is no good doc for realm but i can share my experiences with you:

  1. you can use all transactions like below:

    /**
     * insert or update your model in data base
     * @param basemodel what u want to insert
     */
    public void insertOrUpdate(RealmModel basemodel){
     try {
         realm = Realm.getDefaultInstance();
         realm.executeTransaction(new Realm.Transaction() {
             @Override
             public void execute(Realm realm) {
                 realm.insertOrUpdate(basemodel);
             }
         });
     } finally {
         if(realm != null) {
             realm.close();
         }
     }
    

    }

and in class can see this :

public class MyRealm {
    Realm realm = null;
    public RealmModel results = new RealmModel();
    Context context;//optional

so you can build a class for realm jobs for insert and update or delete and read and anything you want from realm

2.Configuration in realm is too important, you must create a class and extend from application class ,like this:

 public class MyApplication extends Application {

byte[] key = new byte[64];


private byte[] createRealmKey() {
    byte[] key = new byte[64];
    SecureRandom secureRandom = new SecureRandom();
    secureRandom.nextBytes(key);
    return key;
}


@Override
public void onCreate() {
    super.onCreate();

    if (key == null) {
        key=createRealmKey();
    }

    Realm.init(this);

    RealmConfiguration config = new RealmConfiguration.Builder()
            .name("name.realm")
            .schemaVersion(1)
            .encryptionKey(key)
            .deleteRealmIfMigrationNeeded()
            .build();
    Realm.setDefaultConfiguration(config);
}

this is a realm configuration for encrypted data and schemaVersions that will useful for you.

now your answer is here: if you use class and RealmModel in RIGHT way, you can use all thing like databinding and rx with it

see this job:

              RealmModel baseRealmModel = new new RealmModel();

              baseRealmModel = myRealm.realmQueryOfRealmModel();//return a 
          ////realm object for you that can do all with it
              baseRealmModel.setUser(realmUser);
              myRealm.insertOrUpdate(baseRealmModel);

you can ask more questions in comments

Upvotes: 0

Related Questions