Last active
June 8, 2017 11:56
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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