Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Realm file without restarting application #2153

Closed
defaultbr opened this issue Jan 25, 2016 · 16 comments
Closed

Change Realm file without restarting application #2153

defaultbr opened this issue Jan 25, 2016 · 16 comments
Labels

Comments

@defaultbr
Copy link

Hi, im currently using GoogleDrive to backup the Realm database file

and when i need to restore, i just delete the old file and than put the new one from GoogleDrive in its place, but to work i need to restart the application.

so im looking a way to avoid the app restart (not a major problem of course)

is there anyway like: "Realm.disconnect()" and after returning the new file, "Realm.connect()"

@cmelchior
Copy link
Contributor

As long as you have closed all Realm instances you are free to swap the file out, or create a new RealmConfiguration and use that.

RealmConfiguration config = new RealmConfiguration.Builder(context).name("filename").build();
Realm realm = Realm.getInstance(config); // Use old file
realm.close(); // done using old file
overrideRealmFileWithGoogleDriveFile();
realm = Realm.getInstance(config); // Use new file

@defaultbr
Copy link
Author

wow, that was fast, i will try and return here to say ok?

thank you so much

@defaultbr
Copy link
Author

not worked properly, i have a Constants method to set the RealmConfiguration(im in migration number 4)

the method:

 public static void setDefaultConfig(Activity activity) {
                if(defaultConfig == null) {
                        defaultConfig = new RealmConfiguration.Builder(activity).schemaVersion(4).migration(new Migration()).build();
                }
                Realm.setDefaultConfiguration(defaultConfig);
                Realm.getInstance(defaultConfig);
        }

and im using this after the file swap:

 Realm realm = Realm.getDefaultInstance(); // Use old file
                    realm.close(); // done using old file
                    FileUtils.forceDelete(new File(dbPath));
                    FileUtils.copyInputStreamToFile(fileContents.getInputStream(), new File(dbPath));
                    Constants.setDefaultConfig(activity);

but i still need to restart the application to see the changes, everyquery show as empty, after the restart, work perfectly

maybe im doing something wrong, i will try another approach

@cmelchior
Copy link
Contributor

Just changing the file, won't refresh the UI. You still need to open a new Realm instance, load all the data again and refresh the UI

@cmelchior
Copy link
Contributor

@defaultbr Did you solve the problem?

@defaultbr
Copy link
Author

Sorrryy, i forgot to post, not really, was receiving the same problem so i kept the restart app method, right now im doing a code cleanup and will try again

@kneth
Copy link
Member

kneth commented Feb 11, 2016

@defaultbr By the way, will be Realm file on your Google drive be overwritten? I mean, if two devices are accessing the same Realm file, it is not hard to image that the app will be messed up.

Realm is using mmap() to open files, and mmap() doesn't generally work well with network file system like NFS and CIFS. I don't know if Google drive supports mmap().

@cmelchior
Copy link
Contributor

Hi @defaultbr I assume you found a way to make this work. Feel free to reopen if that is not the case.

@defaultbr
Copy link
Author

defaultbr commented Apr 21, 2016

@cmelchior

Sorry for the late post, i was out for a while and now i had to "destroy" my app and restart everything from zero!!

and i stopped again at this part..... i cant close Realm instance im using this in my MainActivity:

  RealmConfiguration config = new RealmConfiguration.Builder(this).schemaVersion(Migration.VERSION).migration(new Migration()).build();
        Realm.setDefaultConfiguration(config);

but how to close instance? its impossible since its used anywhere in other files/classes/methods using the Realm.getDefaultInstance();

i`ve tried this:


     Realm realm = Realm.getDefaultInstance();
        Log.d("CLOSE", "isClosed?: " + realm.isClosed());
        realm.close();
        Log.d("CLOSE", "isClosed?: " + realm.isClosed());

but for both say FALSE, WHY?

and now if i use the onBackPressed to close the mainActivity and try to open the app again, it give me a Exception:

 Caused by: java.lang.IllegalArgumentException: Configurations cannot be different if used to open the same file. 
                                                                      Cached configuration: 

so probrably i was more secure using this in each place i was using the database:

Realm.getInstance(new RealmConfiguration.Builder(this).schemaVersion(Migration.VERSION).migration(new Migration()).build());

anyway, is there any method like:

Realm.closeALLinstances(); or a way to do something like this?

im lost in the cycle of realm, why im getting this exception when i use onBackPressed?

@beeender
Copy link
Contributor

@defaultbr Sorry, but there is no Realm.closeALLinstances(); method.
Realm is using reference counter internally which means if you called getInstance() twice on the same RealmConfiguration in the same thread, you need to call Realm.close() twice in the same thread to close it.

Using Realm.getInstance(someCongfiguration) without catch the returned instance will be a bad practice since you cannot close the Realm instance anymore which would lead to memory leaks.

@defaultbr
Copy link
Author

defaultbr commented Apr 28, 2016

@beeender thanks the explanation, so which way will be the best? since i need to call getInstance in MANY different activities and sometimes inside asynctask?

@sipersso
Copy link

sipersso commented May 25, 2016

Is there a way, (for debugging purposes) to get access to the number of open realms? I am having the same problem as @defaultbr trying to replace the Realm file without restarting the app. The other option I have thought of is to open a open the replaced realm on another path and then something like this

Realm newDbData = getNewDbData();
Realm realm = Realm.getDefaultInstance();

realm.beginTransaction();
realm.deleteAll();
List<MyModel> models = Realm.getDefaultInstance().where(MyModel.class).findAll();
realm.copyToRealmOrUpdate(models);
... repeat for other datatypes
realm.commitTransaction();

This method works and allows me to replace the database content without restarting, but doing deep copies of the entire database is a very expensive operation. Is there any better way?

@sipersso
Copy link

To add to this. For me, it was just about that I was having a Realm open. It was very helpful to set a breakpoint i Realm.getDefaultInstance and in realm.close just to identify where the problem was.

@defaultbr
Copy link
Author

I had so many places where i was using Realm.getDefaultInstance() like a crazy motherf.... firing this in all place at the code, so i left for later...

last week i took the time and patience to clear the code and use the onCreate, onDestroy to build the realm = Realm.getDefaultInstance() and the realm.close(), and of course, now using the setConfiguration at the Application level

this turned the thing so much easier!!

now i can swap everything easy, change database, do backup, restore no matter what 💃

and my question to beeender is pointless, now i know much more about how realm works

thank you all guys =)

TIP for future noobs like me: use Application level to set the Configuration, and for each Activity/Async/etc.. that you NEED to use the realm, use the onCreate and onDestroy, and for async, initiate it at the doInBackGround and close before the return

@sorinns
Copy link

sorinns commented Aug 18, 2019

What would be the correct approach to do this (change the realm file) using React Native?

@kneth
Copy link
Member

kneth commented Aug 19, 2019

@sorinns Maybe you question is better asked at https://github.com/realm/realm-js but you should store your Realm instance in the local state and use componentDidMount() and componentWillUnmount() to open and close it.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

6 participants