gpt4 book ai didi

java - 更深入地了解 Realm 的工作原理?

转载 作者:太空宇宙 更新时间:2023-11-03 13:14:23 26 4
gpt4 key购买 nike

第一季度:请让我知道 implementation 的两种方式有什么不同在下面(大约得到 realm instance )。我想知道哪个更快,内存更轻,推荐什么?

1. 将 Realm 设置为默认值(使用特定配置)

private void setupCustomRealm() {
if (!Utils.isStringHasText(databaseName)) {
databaseName = DbManager.getInstance().getCurrentDb();
}
// get config
RealmConfiguration config = getRealmConfigByDBName(databaseName);
Realm.setDefaultConfiguration(config);
Realm.compactRealm(config);

}

public Realm getCustomRealm() {
if (firstTime) {
setupCustomRealm();
}
return Realm.getDefaultInstance();
}

2 .直接从config中获取Realm
public Realm getCustomRealm(Context context) {
if (!Utils.isStringHasText(databaseName)) {
databaseName = DbManager.getInstance().getCurrentDb();
}
// get config
RealmConfiguration config = getRealmConfigByDBName(context, databaseName);
Realm.compactRealm(config);
return Realm.getInstance(config);
}

第二季度:在我的应用程序中,现在我们考虑两种实现方式。

1:每当我们需要对数据库做一些事情时(在工作线程和 UI 线程中),我们都会创建一个新的 Realm 实例,并在任务完成时关闭它。

2:我们只创建一个Realm实例并让它与应用程序一起存在,当退出应用程序时我们关闭上面的实例。

请解释一下每种方法的优缺点以及推荐的方法(我的应用程序使用 Service 来处理数据库和网络连接)

如果我有 2 个繁重的任务(需要很长时间才能完成它的事务),一个 Realm 实例执行 2 个任务和在 2 个单独线程中的 2 个 Realm 实例上执行 2 个任务有什么区别(我的意思是一个线程有一个 Realm 实例和instance 将执行上述 2 个任务中的 1 个),如果更安全和更快,哪个任务会执行。

如果在执行事务时出现问题会发生什么(例如没有响应或抛出一些异常)

最佳答案

注意:我不是 Realm 的正式人员,但我已经使用 Realm 有一段时间了。

这是 TL;DR version

1.) 有几点值得注意:

  • 一个给定的 Realm 文件只能用相同的 RealmConfiguration 访问。在整个应用程序中,所以 第一个 这里的解决方案更可取(不要为每个 Realm 创建新配置)。
  • Realm.compactRealm(RealmConfig)仅当有 时才有效任何线程上都没有打开的 Realm 实例 .因此,无论是在应用程序启动时,还是在应用程序完成时(我个人发现它会使启动变慢,所以当我的 Activity 计数达到 compactRealm() 时,我调用了 0 ,我使用绑定(bind)到 Activity 的保留 fragment 进行管理 - 但是这就是我)。

  • 2.) 值得注意的是 Realm.getInstance()在第一次调用时创建一个线程本地缓存(缓存在属于同一线程的 Realm 实例之间共享,并增加一个计数器以指示在该给定线程上打开了多少 Realm 实例。当该计数器达到 0 作为在所有实例上调用 realm.close() 的结果,缓存被清除。

    还值得注意的是 Realm实例是线程受限的,所以你需要打开一个新的 Realm在您使用它的任何线程上。这意味着如果你在 IntentService 中使用它,你需要打开一个新的 Realm(因为它在后台线程中)。

    极其重要调用 realm.close()在后台线程上打开的 Realm 实例上。
    Realm realm = null;
    try {
    realm = Realm.getDefaultInstance();
    //do database operations
    } finally {
    if(realm != null) {
    realm.close();
    }
    }

    或 API 19+:
    try(Realm realm = Realm.getDefaultInstance()) {
    //do database operations
    }
  • 当您调用 realm.close()在特定的 Realm 实例上,它会使属于它的结果和对象无效。所以对 open/close 都有意义 Activity Realm onCreate()onDestroy() , 或在 Application 中打开它并共享相同的 UI 线程 Realm 实例以在 UI 线程上进行查询。
  • (在 UI 线程上关闭 Realm 实例并不那么重要,除非您打算在所有实例都关闭后对其进行压缩,但是 必须 在后台线程上关闭 Realm 实例。)

  • 注:调用 RealmConfiguration realmConfig = new RealmConfiguration.Builder(appContext).build()如果您在 Application.onCreate() 中调用它,可能会在某些设备上失败, 因为 getFilesDir()可以返回 null ,所以最好初始化你的 RealmConfiguration只有在第一个 Activity 开始后。

    考虑到所有这些,2)的答案是:
  • 虽然我个人为 UI 线程创建了一个 Realm 实例,但您仍然需要为任何后台线程打开(并关闭!)一个新的 Realm 实例。
  • 我为 UI 线程使用了一个 Realm 实例,因为这样更容易注入(inject),也因为 executeTransactionAsync()RealmAsyncTask如果底层 Realm 实例在它仍在执行时被关闭,它会被取消,所以我真的不希望这种情况发生。 :)
  • 不要忘记,您需要 UI 线程上的 Realm 实例来显示 RealmResults<T>来自 Realm 查询(除非您打算使用 copyFromRealm(),这会使所有内容都使用更多内存并且通常更慢)
  • IntentService像普通的后台线程一样工作,所以你也应该在那里关闭 Realm 实例。

  • 无论是同一个 Realm 实例还是另一个,这两个繁重的任务都可以工作(只要确保在给定线程上有一个 Realm 实例),但我建议一个接一个地连续执行这些任务。

    如果交易过程中出现异常,请调用 realm.cancelTransaction() (文档说开始/提交,但它总是忘记取消)。

    如果您不想手动管理开始/提交/取消,您应该使用 realm.executeTransaction(new Realm.Transaction() { ... }); ,因为它会自动为您调用开始/提交/取消。我个人使用 executeTransaction()到处都是,因为它很方便。

    关于java - 更深入地了解 Realm 的工作原理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38695981/

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