realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.46k stars 1.75k forks source link

Callback for Realm file events: Created/deleted/migrated #4669

Open jpmcosta opened 7 years ago

jpmcosta commented 7 years ago

Goal

My goal is to run initialData transaction asynchronously. However, given my Android application use case, I don't think the new Realm.getInstanceAsync is the best fit.

Expected Results

Get Realm instance synchronously, but execute initialData transaction asynchronously.

Actual Results

With Realm.getInstanceAsync, introduced in Realm 3.2.0, a Realm object is not returned synchronously.

That has implications when you are using dependency injection for the Realm instance, as it would make the workflow much more complex than it needs to be (should I not be using it at all?).

Right now, to initialize data, I'm simply making use of SharedPreferences and running a transaction asynchronously.

Version of Realm

Realm version: 3.2.0

bmeike commented 7 years ago

Hey João! I think I don't quite understand the question. initialData is a way of guaranteeing that the realm is initialized, before anyone sees it. That implies that that nobody can have the realm, before the initialData operation is complete. ... and that implies that if you do it asynchronously, your DI can't be static.

Can I ask you a favor? Can you take this issue to StackOverflow. Totally happy to try to answer it there... and if we come up with something that works for you, it will probably help a bunch of others, too!

-blake

jpmcosta commented 7 years ago

@bmeike I see. I was using initialData to populate the database initially, but not necessarily as a "way of guaranteeing that the realm is initialized, before anyone sees it." I will update my code to reflect that. Thanks.

jpmcosta commented 7 years ago

@bmeike this was a somewhat specific question that was meant to discuss the initial data features of Realm and ultimately propose changes based on my use case and your feedback. Unless I was missing something obvious, which was a real possibility and one of the reasons why I opened the issue, I never expected to receive a StackOverflow kind of answer, as my use case is already working and is simple enough.

Still, I wrote a draft of a question I could post on StackOverflow, but I'm not too sure about posting it. However, if you think it's a question you would like to answer, I'll post it.

Title: Realm initial data asynchronous workflow Question: My goal would be to implement a simple workflow to pre-populate a Realm database, without mandatory data. Example: Reddit's initial subreddits — the app can perfectly work without them, but they are populated initially.

RealmConfiguration's initialData method assumes the initial data is mandatory, and won't return a Realm instance until the data is ready, which causes the UI to freeze.

With the release of Realm 3.2.0, Realm has introduced Realm.getInstanceAsync(), which theoretically should solve the issue, but that method returns a RealmAsyncTask, instead of a Realm instance, calling Callback.onSuccess(Realm) once finished.

That's an issue, because that would make my dependency injection workflow unnecessarily complex.

Currently, I'm making use of SharedPreferences to determine if the initial data needs to be set, and initializing it with a simple async transaction. Is there a better alternative?

Cheers!

cmelchior commented 7 years ago

Hi @jpmcosta No, feature requests should go here :)

It is an interesting use case. By doing an async transaction it also means that you are OK with the Realm instance not being "fully" initialized?

The natural option would be to add something like RealmConfiguration.initialDataAsync() but calling something "initial*" kinda implies that it is setup when the Realm is opened, so that doesn't feel right to me.

If I remember correctly we have heard other use cases for doing other things when a Realm is created, like resetting SharedPrefs or similar (need to dig those up). So I'm thinking that perhaps we should expose a lifecylecallback whenever the Realm is created/reset, and then you could do whatever. Something like:

RealmConfiguration config = new RealmConfiguration.Builder()
  .realmHandler(new RealmCreatedCallback() {
      @override
      public void onRealmCreated(RealmConfiguration config) {
         // Callback when the Realm file is created the first time. Called after inititialData/assetFile has been executed
      }
  })
 .build();

Naming and scope is up for debate of course:

Name:

Possible scope:

Would something like that work for you?

jpmcosta commented 7 years ago

Would something like that work for you?

@cmelchior Yes, that would be perfect! I also envisioned something like initialDataAsync, but the lifecyclecallback should work much better.

Edit: I didn't read the comma! Thanks for your answer.

cmelchior commented 7 years ago

4083 described a use where this type of closure would make sense:

RealmFileEventHandler handler = new RealmFileEventHandler() {
  @Override
  public void onRealmDeleted(RealmConfiguration config) { ... }

  @Override
  public void onRealmCreated(RealmConfiguration config) { ... }

  // Use case in #4083
  @Override
  public void onRealmMigrated(long from, long to, RealmConfiguration config) { ... }
};