【问题标题】:How to properly manage realm in Android to data bind views, but close all realm instances?如何在 Android 中正确管理领域以数据绑定视图,但关闭所有领域实例?
【发布时间】:2023-03-20 06:09:01
【问题描述】:

如何在 Android 中正确管理领域,以确保所有数据库实例最终都关闭,但保持打开足够长的时间以便 View 到 DataBind 托管对象并观察变化?

我想知道在与 Realm 实例交互时是否有确保可以观察数据的最佳实践,以及对数据库的每个引用都正确关闭。我一直在寻找解决这个问题的好方法,但到目前为止,它似乎要么是 Realm 的一个主要下降点,要么是一个保守的秘密。在之前的项目中,我在与数据库交互时没有正确关闭 Realm 实例,这最终导致了巨大的麻烦和进一步的重构。

我正在开始一个新项目,并希望确保我从一开始就正确设置了所有内容。我正在开发的应用程序将接收推送通知,该通知将触发来自服务器的更新并将更改存储在数据库中。我想用 Realm 观察数据库中的相关数据,以便在数据库更改时数据绑定视图可以自动更新。如果我错了,请纠正我,但我的理解是,要观察数据库,从中获取数据的 Realm 实例必须保持打开状态。这意味着我不能有一个单独的存储库来打开一个新的 Realm 实例,获取我需要的模型,然后将其传回,因为我无法观察到变化。

我想出的解决方案是使用 3 种与数据库交互的方式创建一个存储库层。这三个选项将是复制、更新和收听。复制和更新函数将在单个块中打开和关闭领域实例,如下所示:

public RealmObject copyOrUpdate() {
    Realm realm = Realm.getDefaultInstance()
    try {
         // Transaction
    } finally {
        realm.close()
    }
}

但是,当我需要观察模型时,我不能使用它,因为数据库将在观察视图被销毁之前关闭。因此,为了跟踪领域实例,我将在创建每个需要 observable 的 ViewModel 时打开一个新实例。然后当我需要一个托管对象时,我将传递领域实例:

public RealmObject observeObject(Realm realm) {
    return // Managed object
}

当 View 被销毁并且 ViewModel 被清除时,最后关闭 Realm 实例。从我目前对 Realm 的理解来看,老实说,我想不出另一种或更好的方法来做到这一点,并且通过在线阅读,除了这篇没有答案的帖子之外,我找不到其他有相同或类似问题的人:

How to properly separate Realm from the rest of the app?

任何帮助、见解或建议将不胜感激,这样我就可以提高对 Realm 的理解并避免进一步的头痛。

我还想知道观察 Realm 数据库的最佳方式,因为 Realm 似乎不提供对 LiveData 的支持,并且注册/注销 RealmChangeListeners 似乎是一场等待发生的意外。是否有官方支持的处理 LiveData 的方式,或者我是否需要学习正确使用 RealmChangeListeners?最后,我在过去使用 Room 取得了很多成功,并且觉得它是一个更好的解决方案,因为它被正式支持为 Android 架构组件。我看到争论的双方都有人,但我有什么具体的理由应该远离 Room 吗?

在此先感谢您的任何帮助或指导。

【问题讨论】:

  • 在最初发布这个问题后,我继续做了大量的研究,答案仍然不清楚。随着 Google 推出 Android 架构组件,似乎没有任何充分的理由使用 Realm over Room。我已经开始在生产中使用 Room 并且对结果非常满意;尽管迁移需要更长的时间,但能够直接访问和观察数据库中的 LiveData 对象使得数据绑定更加容易和更加健壮。

标签: java android data-binding realm android-livedata


【解决方案1】:

领域没有好的文档,但我可以与您分享我的经验:

  1. 您可以使用以下所有交易:

    /**
     * insert or update your model in data base
     * @param basemodel what u want to insert
     */
    public void insertOrUpdate(RealmModel basemodel){
     try {
         realm = Realm.getDefaultInstance();
         realm.executeTransaction(new Realm.Transaction() {
             @Override
             public void execute(Realm realm) {
                 realm.insertOrUpdate(basemodel);
             }
         });
     } finally {
         if(realm != null) {
             realm.close();
         }
     }
    

    }

在课堂上可以看到这个:

public class MyRealm {
    Realm realm = null;
    public RealmModel results = new RealmModel();
    Context context;//optional

这样您就可以为领域作业构建一个类,用于插入和更新或删除和读取以及您想要从领域获得的任何内容

2.realm中的配置太重要了,你必须创建一个类并从应用类扩展,像这样:

 public class MyApplication extends Application {

byte[] key = new byte[64];


private byte[] createRealmKey() {
    byte[] key = new byte[64];
    SecureRandom secureRandom = new SecureRandom();
    secureRandom.nextBytes(key);
    return key;
}


@Override
public void onCreate() {
    super.onCreate();

    if (key == null) {
        key=createRealmKey();
    }

    Realm.init(this);

    RealmConfiguration config = new RealmConfiguration.Builder()
            .name("name.realm")
            .schemaVersion(1)
            .encryptionKey(key)
            .deleteRealmIfMigrationNeeded()
            .build();
    Realm.setDefaultConfiguration(config);
}

这是对您有用的加密数据和 schemaVersions 的领域配置。

现在你的答案在这里: 如果你以正确的方式使用 class 和 RealmModel,你可以使用所有的东西,比如数据绑定和 rx

查看这份工作:

              RealmModel baseRealmModel = new new RealmModel();

              baseRealmModel = myRealm.realmQueryOfRealmModel();//return a 
          ////realm object for you that can do all with it
              baseRealmModel.setUser(realmUser);
              myRealm.insertOrUpdate(baseRealmModel);

您可以在 cmets 中提出更多问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多