gpt4 book ai didi

java - 管理服务和应用程序之间的 Realm

转载 作者:行者123 更新时间:2023-12-02 13:01:35 24 4
gpt4 key购买 nike

我正在开发一个 Android 应用程序,该应用程序在服务中接收一些 BLE 数据,然后将它们存储到 Realm 数据库中,并明显显示在 Activities 上 fragment 。我设置了一个名为 RealmManagerSingleton 类,它使用单个 Realm 实例(带有 getDefaultInstance)来执行事务和查询。如果我调用 RealmManager 方法将新数据存储到 Realm,则会引发异常,因为我在不同的线程上使用 Realm。在此示例中,我无法从服务和 Activity 中调用 RealmManager.sharedInstance().userWithEmail("pippo"):

public class RealmManager {

private static Realm realmDB;
private static RealmManager ourInstance;

public RealmManager(){
realmDB = Realm.getDefaultInstance();
}

public static RealmManager sharedInstance(){
if(ourInstance == null)
ourInstance = new RealmManager();
}

public User userWithEmail(String email){
User user = realmDB.where(User.class).equalTo(USER_EMAIL, email).findFirst();
return user;
}
}

如果我在每个方法上实例化一个新的 Realm 实例,然后在最后调用 Realm.close,我无法跨应用程序使用 Realm 结果,因为 Realm 实例已关闭。在此示例中,我无法在调用者中使用user,因为实例已关闭:

public ArrayList<Patient> getPatientsForLoggedUser() {
final Realm realmDB =
Realm.getInstance(RealmManager.getDefaultInstance();
try {
ArrayList<Patient> patients = new ArrayList<>(realmDB.where(Patient.class).equalTo("user.email", loggedUser().getEmail()).findAllSorted("firstName", Sort.ASCENDING));
return patients;
} finally {
if(realmDB != null)
realmDB.close();
}
}

如何使用 RealmManager 类从应用程序和服务中保存和检索所有应用程序的数据库数据?

最佳答案

你不能像这样创建一个单一的 Realm。

通常您需要ThreadLocal<Realm>为此,但 Realm 已经使用所谓的 RealmCache 在内部管理此问题,看起来有点像这样:

private static class RefAndCount {
// The global Realm instance in this thread.
private final ThreadLocal<BaseRealm> localRealm = new ThreadLocal<>();

// How many local references to this Realm instance in this thread.
private final ThreadLocal<Integer> localCount = new ThreadLocal<>();

// How many threads have instances refer to this configuration.
private int globalCount = 0;
}

private synchronized <E extends BaseRealm> E doCreateRealmOrGetFromCache(RealmConfiguration configuration) {
RefAndCount refAndCount = refAndCountMap.get(RealmCacheType.valueOf(Realm.class));

if (refAndCount.localRealm.get() == null) {
// Creates a new local Realm instance
BaseRealm realm = Realm.createInstance(this);
refAndCount.localRealm.set(realm);
refAndCount.localCount.set(0);

refAndCount.globalCount++;
}

Integer refCount = refAndCount.localCount.get();
refAndCount.localCount.set(refCount + 1);

//noinspection unchecked
return (E) refAndCount.localRealm.get();
}


synchronized void release(BaseRealm realm) {
String canonicalPath = realm.getPath();
RefAndCount refAndCount = refAndCountMap.get(RealmCacheType.valueOf(Realm.class));
Integer refCount = refAndCount.localCount.get();
if (refCount == null) {
refCount = 0;
}

if (refCount <= 0) {
RealmLog.warn("%s has been closed already. refCount is %s", canonicalPath, refCount);
return;
}

refCount -= 1;

if (refCount == 0) {
refAndCount.localCount.set(null);
refAndCount.localRealm.set(null);

refAndCount.globalCount--;
if (refAndCount.globalCount < 0) {
// Should never happen.
throw new IllegalStateException("Global reference counter of Realm" + canonicalPath + " got corrupted.");
}

realm.doClose();

if (getTotalGlobalRefCount() == 0) {
configuration = null;
}
} else {
refAndCount.localCount.set(refCount);
}
}

考虑到这一点,我们学到的是:

1.) Realm.getDefaultInstance() 增加本地计数,并打开一个新的全局线程本地 Realm 实例如果localCount 0 -> 1

2.) realm.close()减少本地计数

3.) 如果 localCount 1 -> 0 ,然后全局线程本地Realm实例被释放

4.) 所有这些方法都是 synchronized实现中

<小时/>

考虑到这一点,您可能不应该为所有线程创建全局 Realm 实例。主要是因为您要在现有的线程本地缓存之上创建线程本地缓存,这会变得很棘手。虽然你可以检查this question as an example from daniel christopher (gist)。

<小时/>

通常,您应该提供本地 Realm 实例并关闭它们。

documentation describes the best practices for managing Realm instance lifecycle ,尽管我个人更喜欢每个线程只保留 1 个 Realm 实例。

关于java - 管理服务和应用程序之间的 Realm ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44282526/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com