Как правильно управлять областью в Android для представления привязки данных, но закрыть все экземпляры области?

Как правильно управлять областью в Android, чтобы гарантировать, что все экземпляры базы данных в конечном итоге будут закрыты, но оставлены открытыми достаточно долго для управляемых объектов View to DataBind и наблюдения за изменениями?

Я хочу знать, существует ли наилучшая практика взаимодействия с экземплярами Realm, которая обеспечивает возможность наблюдения за данными, а также правильное закрытие каждой ссылки на базу данных. Я искал хороший способ решить эту проблему, но до сих пор это кажется либо серьезным недостатком Realm, либо хорошо охраняемым секретом. В предыдущем проекте я не закрывал должным образом экземпляры Realm при взаимодействии с базой данных, и это в конечном итоге привело к огромным головным болям и дальнейшим рефакторингам.

Я начинаю новый проект и хочу убедиться, что все настроено правильно с самого начала. Приложение, над которым я работаю, будет получать push-уведомления, которые запускают обновление с сервера и сохраняют изменения в базе данных. Я хочу наблюдать за связанными данными в базе данных с Realm, чтобы представления с привязкой к данным могли автоматически обновляться при изменении базы данных. Поправьте меня, если я ошибаюсь, но я так понимаю, что для наблюдения за базой данных экземпляр Realm, из которого были извлечены данные, должен оставаться открытым. Это означает, что у меня не может быть единого репозитория, который открывает новый экземпляр Realm, извлекает нужную мне модель, а затем передает ее обратно, поскольку я не смогу наблюдать за изменениями.

Решение, которое я придумал, состоит в том, чтобы создать слой репозитория с тремя способами взаимодействия с базой данных. Три варианта: копировать, обновить и прослушать. Функции копирования и обновления будут открывать и закрывать экземпляр области в одном блоке, примерно так:

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

Однако я не могу использовать это, когда мне нужно наблюдать за моделью, поскольку база данных будет закрыта до того, как наблюдательное представление будет уничтожено. Поэтому, чтобы отслеживать экземпляр области, я буду открывать новый экземпляр при создании каждой ViewModel, для которой требуется наблюдаемое. Затем, когда мне нужен управляемый объект, я передам экземпляр области:

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

И, наконец, закройте экземпляр Realm, когда представление будет уничтожено, а модель представления будет очищена. Исходя из моего текущего понимания Realm, я, честно говоря, не могу придумать другого или лучшего способа сделать это, и, читая в Интернете, я не могу найти других людей с такими же или похожими проблемами, кроме этого поста, который остался без ответа:

Как правильно отделить Realm от остальной части приложение?

Любая помощь, идеи или советы будут высоко оценены, чтобы я мог улучшить свое понимание Realm и избежать головной боли в будущем.

Я также хотел бы знать, как лучше всего наблюдать за базой данных Realm, так как Realm, похоже, не предлагает поддержку LiveData, а регистрация/отмена регистрации RealmChangeListeners кажется несчастным случаем, ожидающим своего часа. Есть ли официально поддерживаемый способ обработки LiveData или мне нужно научиться правильно использовать RealmChangeListeners? Наконец, я добился большого успеха в прошлом, используя Room, и считаю, что это лучшее решение, поскольку оно официально поддерживается как компонент архитектуры Android. Я вижу людей с обеих сторон дебатов, но есть ли какие-то конкретные причины, по которым мне следует держаться подальше от Room?

Заранее спасибо за любую помощь или руководство.


person thebillington    schedule 12.12.2019    source источник
comment
Я продолжал проводить много исследований после первоначальной публикации этого вопроса, и ответ до сих пор неясен. С компонентами архитектуры Android, продвигаемыми Google, похоже, нет веской причины использовать Realm вместо Room. Я начал использовать Room в продакшене и очень доволен результатами; хотя миграция занимает больше времени, возможность прямого доступа и наблюдения за объектами LiveData в базе данных сделала привязку данных намного проще и надежнее.   -  person thebillington    schedule 20.01.2020


Ответы (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. Конфигурация в области слишком важна, вы должны создать класс и расширить его из класса приложения, например:

 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);
}

это конфигурация области для зашифрованных данных и версий схемы, которые будут вам полезны.

теперь ваш ответ здесь: если вы используете класс и 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);

вы можете задать дополнительные вопросы в комментариях

person alireza daryani    schedule 15.12.2019