Skip to content

Instantly share code, notes, and snippets.

@magillus
Last active June 8, 2017 11:56
Show Gist options
  • Save magillus/7b32415e2da13ccc32879978a860fc13 to your computer and use it in GitHub Desktop.
Save magillus/7b32415e2da13ccc32879978a860fc13 to your computer and use it in GitHub Desktop.
Realm Context wrapper, for easy opening realm and closing with action and data return (copyFromRealm).
// copied from Reactive X functions - have your own if no need for full Rx in your project.
package io.reactivex.functions;
/**
* A functional interface that takes a value and returns another value, possibly with a
* different type and allows throwing a checked exception.
*
* @param <T> the input value type
* @param <R> the output value type
*/
public interface Function<T, R> {
/**
* Apply some calculation to the input value and return some other value.
* @param t the input value
* @return the output value
* @throws Exception on error
*/
R apply(T t) throws Exception;
}
package com.example.mat.rxjavaplayground.rxutil;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import io.reactivex.functions.Function;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmObject;
import timber.log.Timber;
/**
* Realm db wrapper for easier execution on same thread actions and transactions.
*
* Copyright 2017 Mateusz Perlak - http://www.apache.org/licenses/LICENSE-2.0
*/
public class RealmContext {
/**
* Realm configuration used for initializing realm.s
*/
protected RealmConfiguration realmConfiguration;
/**
* Create instance of RealmContext for db name and version.
*
* @param context
* @param name
* @param version
*/
public RealmContext(Context context, String name, int version, Object module) {
this(context, new RealmConfiguration.Builder()
.name(name)
.deleteRealmIfMigrationNeeded()
.schemaVersion(version)
.modules(module)
.build());
}
public RealmContext(Context context, RealmConfiguration configuration) {
Realm.init(context);
this.realmConfiguration = configuration;
}
/**
* Wraps function execution with Realm object that is released after function is run.
*
* @param function function that will use the Realm instance
* @param <R> return type from the function
* @return return value from the function
*/
public <R> R withRealm(Function<Realm, R> function) {
try (Realm realm = Realm.getInstance(realmConfiguration)) {
try {
return function.apply(realm);
} catch (Exception e) {
Timber.w(e, "Error calling function on Realm.");
}
}
return null;
}
/**
* Wraps function execution with Realm object that is released after function is run.
*
* @param function function that will use the Realm instance
* @param <R> return type from the function
* @return return value from the function
*/
public <R> R withRealmCopy(Function<Realm, R> function) {
try (Realm realm = Realm.getInstance(realmConfiguration)) {
try {
return copyFromRealm(realm, function.apply(realm));
} catch (Exception e) {
Timber.w(e, "Error calling function on Realm.");
}
}
return null;
}
/**
* Wraps function to run in transaction, if realm is already in transaction will start not start or commit new transaction.
*
* @param realm
* @param function
* @param <R>
* @return
*/
public <R> R withTransaction(@Nullable Realm realm, Function<Realm, R> function) {
if (realm != null) {
boolean wasInTransaction = realm.isInTransaction();
try {
if (!wasInTransaction) {
realm.beginTransaction();
}
R retValue = function.apply(realm);
if (!wasInTransaction) {
realm.commitTransaction();
}
return retValue;
} catch (Exception ex) {
Timber.w(ex, "Error running realm with transaction.");
return null;
} finally {
// if all good should not be in transaction, cancel otherwise
if (!wasInTransaction && realm.isInTransaction()) {
realm.cancelTransaction();
}
}
} else {
return withRealm(newRealm -> withTransaction(newRealm, function));
}
}
/**
* Wraps function execution with Realm transaction and commits after function is run.
* It will commit transaction if function run without errors and cancel transaction if there were errors.
*
* @param function function that will use realm transaction.
* @param <R> return type from the function.
* @return return value from the function.
*/
public <R> R withTransaction(Function<Realm, R> function) {
return withTransaction(null, function);
}
/**
* Checks if null and copies from realm the object.
*
* @param realm
* @param object
* @param <R>
* @return
*/
@Nullable
public static <R> R copyFromRealm(@NonNull Realm realm, @Nullable R object) {
if (object != null) {
if (object instanceof RealmObject) {
return (R) realm.copyFromRealm((RealmObject) object);
} else {
return object;
}
}
return null;
}
/**
* Copies list of RealmObjects from Realm
* @param realm
* @param list
* @param <R>
* @return
*/
public static <R extends RealmObject> List<R> copyFromRealmList(@NonNull Realm realm, @NonNull List<R> list) {
if (list.isEmpty()) {
return Collections.emptyList();
} else {
return realm.copyFromRealm(list);
}
}
}
public class User extends RealmObject {
@PrimaryKey
public long id;
public String name;
public User(long id, String name) {
this.id = id;
this.name = name;
}
}
User userA = new User(1,"test A");
User userB = new User(2,"test B");
int size = realmContext.withRealm(realm-> {
List<User> usersList = realm.where(User.class).findAll();
return usersList.size();
});
Assert.assertEquals(0,size);
realmContext.withTransaction(realm->{
realm.insertOrUpdate(userA);
return true;// must return something
});
size = realmContext.withRealm(realm-> {
List<User> usersList = realm.where(User.class).findAll();
return usersList.size();
});
Assert.assertEquals(1,size);
realmContext.withTransaction(realm->{
realm.insertOrUpdate(userB);
return true;// must return something
});
size = realmContext.withRealm(realm-> {
List<User> usersList = realm.where(User.class).findAll();
return usersList.size();
});
Assert.assertEquals(2,size);
User userAChanged = realmContext.withTransaction(realm-> {
User user = realm.where(User.class).equalTo("id", 1).findFirst();
user.name = "test Ab";
return realm.copyFromRealm(user);
});
Assert.assertEquals("test Ab", userAChanged.name);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment