我是否正确实现了EpicPandaForce的RealmManager? [英] Have I implemented EpicPandaForce's RealmManager correctly?
问题描述
我是Realm(和Android开发)的新手,我想使用Singleton类简化Realm数据管理,以便我的朋友更轻松地在我们的小组项目中使用.
I am new to Realm (and Android development) and I would like to use a Singleton class to simplify Realm data management so it's easier for my friends to use in our group project.
EpicPandaForce在在此处编写了一个名为RealmManager的单例类,但是我找不到实现它的示例,因此这是我尝试过的:
EpicPandaForce have written a singleton class called RealmManager here, but I couldn't find an example in implementing it, so this is what I have tried:
public class RealmManager {
private static RealmManager instance;
private final ThreadLocal<Realm> localRealm = new ThreadLocal<>();
RealmManager(){}
public synchronized static RealmManager getInstance(){
if(instance == null){
instance = new RealmManager();
}
return instance;
}
public Realm openLocalInstance() {
Realm realm = Realm.getDefaultInstance();
if(localRealm.get() == null) {
localRealm.set(realm);
}
return realm;
}
public Realm getLocalInstance() {
Realm realm = localRealm.get();
if(realm == null) {
throw new IllegalStateException("No open Realms were found on this thread.");
}
return realm;
}
public void closeLocalInstance() {
Realm realm = localRealm.get();
if(realm == null) {
throw new IllegalStateException(
"Cannot close a Realm that is not open.");
}
realm.close();
if(Realm.getLocalInstanceCount(Realm.getDefaultConfiguration()) <= 0) {
localRealm.set(null);
}
}
public void storePreferenceDao(int userID, String rank){
final PreferenceDao preferenceDao = new PreferenceDao();
preferenceDao.setUserID(userID);
preferenceDao.setRank(rank);
openLocalInstance();
getLocalInstance().executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(preferenceDao);
}
}, new Realm.Transaction.OnSuccess(){
@Override
public void onSuccess(){
System.out.println("Data is stored successfully!");
}
}, new Realm.Transaction.OnError(){
@Override
public void onError(Throwable error){
System.out.println("There is an error in storePreferenceDao()");
}
});
closeLocalInstance();
}
因此,当我的朋友想要存储一些数据时,他们可以使用:
So when my friends want to store some data, they can just use:
RealmManager.getInstance().storePreferenceDao(123, "Alpaca");
这是应该使用的方式还是多余的?如何提高效率?
Is this how it is supposed to be used or is it redundant? How can I make it more efficient?
推荐答案
实际上,在这种情况下,仍然只能从UI线程调用该方法,并且应该在事务回调中关闭本地实例(否则onSuccess/onError不会被调用)
Actually in this case, that method can still be called only from UI thread, and the local instance should be closed in the transaction callback (otherwise the onSuccess/onError won't be called)
如果可以的话,您可以创建一种可以在bg线程上执行的方法,如果已经在bg线程上,则可以在当前线程上执行
You could make a method that is able to execute on bg thread if able, and on current thread if already on a bg thread
// method in RealmManager
public final void runTransaction(Realm.Transaction transaction) {
runTransaction(transaction, null, null);
}
public final void runTransaction(Realm.Transaction transaction, Realm.Transaction.OnSuccess onSuccess) {
runTransaction(transaction, onSuccess, null);
}
public final void runTransaction(Realm.Transaction transaction, Realm.Transaction.OnSuccess onSuccess, Realm.Transaction.OnError onError) {
Realm realm = openLocalInstance();
if(realm.isAutoRefresh()) {
realm.executeTransactionAsync(transaction, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
try {
if(onSuccess != null) {
onSuccess.onSuccess();
}
} finally {
closeLocalInstance();
}
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable e) {
try {
if(onError != null) {
onError.onError(e);
}
} finally {
closeLocalInstance();
}
}
});
} else {
try {
realm.executeTransaction(transaction);
if(onSuccess != null) {
onSuccess.onSuccess();
}
} catch(Exception e) {
if(onError != null) {
onError.onError(e);
}
throw new RuntimeException(e);
} finally {
closeLocalInstance();
}
}
}
如果添加此方法,则现在可以执行事务,如果可能的话,将通过async
事务方法在后台线程上执行;如果不在循环程序线程上,则使用synchronous
事务方法(例如后台线程)
If you add this method, then you can now execute a transaction that will either be executed on background thread via async
transaction method if possible, using synchronous
transaction method if not on a looper thread (f.ex. background thread)
您现在可以通过这种方式
This way you can now do
public void storePreferenceDao(int userID, String rank) {
final PreferenceDao preferenceDao = new PreferenceDao();
preferenceDao.setUserID(userID);
preferenceDao.setRank(rank);
runTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(preferenceDao);
}
}, new Realm.Transaction.OnSuccess(){
@Override
public void onSuccess(){
System.out.println("Data is stored successfully!");
}
}, new Realm.Transaction.OnError(){
@Override
public void onError(Throwable error){
System.out.println("There is an error in storePreferenceDao()");
}
});
}
或者只是
public void storePreferenceDao(int userID, String rank) {
final PreferenceDao preferenceDao = new PreferenceDao();
preferenceDao.setUserID(userID);
preferenceDao.setRank(rank);
runInTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(preferenceDao);
}
});
}
您知道,我一直觉得我应该在该示例中添加runTransaction()
方法.但是,是否应该默认使用executeTransactionAsync
(如果有的话).
You know, I always felt I should add a runTransaction()
method to that example. Whether it should default to using executeTransactionAsync
by default if able or not is up for debate, though.
这篇关于我是否正确实现了EpicPandaForce的RealmManager?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!