您好我已经完成了Realm中的最佳实践,根据它,处理Realm实例的最佳方法是使用onCreate()
在Activity的relam = Realm.getDefaultInstance()
方法中打开realm实例并将其关闭onDestroy()
使用realm.close()
。
但是目前我的代码中有以下单例结构。我需要了解以下单例结构的优缺点,而不是领域文档中提出的最佳实践。
这是我的代码:方法1
public class RealmManager {
private static final String TAG = "RealmManager";
private RealmAsyncTask transactionManager;
private static RealmManager mInstance = null;
public static RealmManager getInstance() {
if (mInstance == null)
mInstance = new RealmManager();
return mInstance;
}
private Realm mRealm;
protected RealmManager() {
mRealm = Realm.getDefaultInstance();
}
public void saveOrUpdateChatChannel(ChatChannel channel) {
mRealm = Realm.getDefaultInstance();
mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(@NonNull Realm bgRealm) {
bgRealm.copyToRealmOrUpdate(channel);
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
Log.e(TAG,"Failed to update Channel");
}
});
}
public void deleteChatChannel(String channelID, OnRealmDatabaseListener mRealmListener) {
mRealm = Realm.getDefaultInstance();
mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(@NonNull Realm realm) {
RealmResults<ChatChannel> result = realm.where(ChatChannel.class).equalTo("channelId", channelID).findAll();
result.deleteAllFromRealm();
}
}, new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
if (mRealmListener != null)
mRealmListener.isDatabaseOperationSuccess(channelID, true);
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(@NonNull Throwable error) {
}
});
}
public void closeRealm() {
if (mRealm != null) {
mRealm.close();
}
if (transactionManager != null) {
transactionManager.cancel();
}
}
}
因此,在方法1中,我将使用RealmManager.getInstance()
在我的活动,服务,意图服务中创建领域实例,然后继续进行交易。在我的所有活动onDestroy()
方法中,我使用RealmManager.closeRealm()
关闭领域。所以我的问题是,如果在Activity RealmManager.closeRealm()
中调用的onDestroy()
会影响在Service中执行的任何事务吗?
这是我的代码:方法2
public class RealmManager {
private static RealmManager mInstance = null;
public static RealmManager getInstance() {
if (mInstance == null)
mInstance = new RealmManager();
return mInstance;
}
private Realm mRealm;
protected RealmManager(){
mRealm = Realm.getDefaultInstance();
}
public void addClockModel(ClockRLM clockRLM,OnRealmDatabaseListener mRealmListener){
RealmAsyncTask transactionManager = mRealm.executeTransactionAsync(realm -> realm.copyToRealm(clockRLM), new Realm.Transaction.OnSuccess() {
@Override
public void onSuccess() {
Log.d("Clocke ", "Inserted TimeStamp " + clockRLM.getTimeStamp());
if (mRealmListener != null)
mRealmListener.isDatabaseOperationSuccess(clockRLM,true);
if (transactionManager != null)
transactionManager.cancel();
}
}, new Realm.Transaction.OnError() {
@Override
public void onError(Throwable error) {
if (transactionManager != null)
transactionManager.cancel();
}
});
}
}
因此,在方法2中,我将使用RealmManager.getInstance()
在我的活动,服务,意图服务中创建领域实例,然后继续进行交易。如果我使用方法2,我不知道在哪里关闭领域。如果我不在任何地方关闭它,只有当应用程序关闭时,RealmManager才会被销毁,并且realm实例将被销毁。或者我需要在应用程序级别关闭realm实例(我不确定是否可以在应用程序级别关闭实例)。
在方法1和方法2中哪一个更好。或者使用onCreate()
在活动的relam = Realm.getDefaultInstance()
方法中打开领域实例并使用{在onDestroy()
中关闭它更好{1}}。
答案 0 :(得分:0)
Realm很难在&#34;单身经理下使用&#34;因为Realm.getDefaultInstance()
可能看起来像是你得到的东西是单身&#34;但它确实不是。领域的实例是thread-local
和reference-counted
,每次调用getInstance()
都会增加引用计数,而close()
会减少引用计数。
我已经多次说过open()
会有更好的名字,但我得出的结论太晚了:)
首先,你的Singleton方法不好的原因是:
只能从首次调用RealmManager.getInstance()
的线程调用方法,这个线程应该是UI线程(但不能保证)
您希望在1个异步事务中执行每个1个操作的硬编码,因此您无法在后台线程中使用此东西
为了使一个可以在任何线程上调用的域管理器,并且UI线程在后台线程使用同步事务时使用异步事务,您需要使用method like this。
此外,您需要跟踪该给定线程的开放Realm实例,以便您可以在任何地方访问它,而无需增加引用计数。
public class RealmManager {
private final ThreadLocal<Realm> localRealm = new ThreadLocal<>();
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);
}
}
有了这样的课程,你可以这样做:
try {
realmManager.openLocalInstance();
// Realm is open and can be accessed on this thread with `realmManager.getLocalInstance()`
// also all your methods in the RealmManager can use `getLocalInstance()`
} finally {
realmManager.closeLocalInstance();
}
我刚刚创建了一个库wraps Realm in such a way that it eliminates the need for manual reference counting,但它从未真正流行过。如果好奇,请查看来源。