Skip to content

Instantly share code, notes, and snippets.

@zacheusz
Last active November 20, 2017 19:39
Show Gist options
  • Save zacheusz/66c79df90b22a581d6f0 to your computer and use it in GitHub Desktop.
Save zacheusz/66c79df90b22a581d6f0 to your computer and use it in GitHub Desktop.
import android.util.Log;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmObject;
import io.realm.RealmObjectSchema;
import io.realm.RealmSchema;
import static java.lang.String.format;
/**
* Created by zacheusz on 16/03/16.
* https://github.com/realm/realm-java/issues/469#issuecomment-196798253
*/
public class PrimaryKeyFactory {
/** primary key field name */
private static final String PRIMARY_KEY_FIELD = "id";
/**
* Singleton instance.
*/
private final static PrimaryKeyFactory instance = new PrimaryKeyFactory();
/**
* Maximum primary key values.
*/
private Map<Class<? extends RealmObject>, AtomicLong> keys;
/**
* get the singleton instance
* @return singleton instance
*/
public static PrimaryKeyFactory getInstance() {
return instance;
}
/**
* Initialize the factory. Must be called before any primary key is generated
* - preferably from application class.
*/
public synchronized void initialize(final Realm realm) {
if (keys != null) {
throw new IllegalStateException("already initialized");
}
// keys field is used as an initialization flag at the same time
keys = new HashMap<>();
final RealmConfiguration configuration = realm.getConfiguration();
final RealmSchema realmSchema = realm.getSchema();
//using RealmConfiguration#getRealmObjectClasses because
// RealmSchema#getAll() returns RealmObjectSchema with simple class names only
for (final Class<? extends RealmObject> c : configuration.getRealmObjectClasses()) {
final RealmObjectSchema objectSchema = realmSchema.get(c.getSimpleName());
Log.i(getClass().getSimpleName(), format("schema for class %s : %s", c.getName(), objectSchema));
if (objectSchema != null && objectSchema.hasPrimaryKey()) {
Number keyValue = null;
try {
keyValue = realm.where(c).max(PRIMARY_KEY_FIELD);
} catch (ArrayIndexOutOfBoundsException ex) {
Log.d(getClass().getSimpleName(), format("error while getting number primary key %s " +
" for %s",PRIMARY_KEY_FIELD, c.getName()), ex);
}
if (keyValue == null) {
Log.w(getClass().getSimpleName(), format("can't find number primary key %s " +
" for %s.",PRIMARY_KEY_FIELD, c.getName()));
} else {
keys.put(c, new AtomicLong(keyValue.longValue()));
}
}
}
}
/**
* Automatically create next key for a given class.
*/
public synchronized long nextKey(final Class<? extends RealmObject> clazz) {
if (keys == null) {
throw new IllegalStateException("not initialized yet");
}
AtomicLong l = keys.get(clazz);
if (l == null) {
Log.i(getClass().getSimpleName(), "There was no primary keys for " + clazz.getName());
//RealmConfiguration#getRealmObjectClasses() returns only classes with existing instances
//so we need to store value for the first instance created
l = new AtomicLong(0);
keys.put(clazz, l);
}
return l.incrementAndGet();
}
}
@Felipe00
Copy link

Hey, in line 54 you have:
for (final Class<? extends RealmObject> c : configuration.getRealmObjectClasses()) { }
But Android Studio requires RealmModel instead of RealmObject.

@jalqa
Copy link

jalqa commented Nov 11, 2016

I know the previous comment was a long time ago, but im posting this in case someone else has the same problem, just change line 30 private Map<Class<? extends RealmObject>, AtomicLong> keys; to private Map<Class<? extends RealmModel>, AtomicLong> keys; although RealmModel is an interface and should use implements instead of extends, it will work in this context using wildcards, then change line 54 RealmObject to RealmModel too (using Realm 2.1.1 ) by the way nice and useful class!!

@eddieberklee
Copy link

@jalqa +1 exactly what I did and it works too though I was initially uncomfortable and wondered whether the wildcard class extending RealmModel would work.

tldr; replace all instances of RealmObject with RealmModel and it should just work.

@marto-k
Copy link

marto-k commented Feb 14, 2017

I initialised the code but i'm wondering how do i initialize the xml .As in do you leave the id value empty or use same id in all textviews?

@Misayanice
Copy link

if i add data,then delete data,”nextKey” has problem!

@Felipe00
Copy link

Misayanice commented on 15 Mar
if i add data,then delete data,”nextKey” has problem!

What problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment