RealmChangeListener не выполняется при добавлении вскоре после асинхронной записи

Короче говоря: я не знаю, почему мой RealmChangeListener не срабатывает, как предполагалось при определенных обстоятельствах, и ищу совет о том, почему RealmChangeListener не мог работать.

Обновление: я подтвердил, что RealmResults оставаться в силе = правда; загружен = ложь. Если я выполню RealmResults.load() после добавления прослушивателя изменений он выдаст неопределенный Throwing Exception 7 в журнале и BadVersionException когда я иду через источник Царства. Я думаю, что это исключение имеет некоторый смысл, асинхронная запись обновила Realm и поэтому запрос, кажется, больше не работает. Тем не менее, оба executeTransactionAsync что пишет в MainActivity а также асинхронные запросы запускаются из основного потока.

-

У меня есть MainActivity, в которой после нажатия кнопки будет выполняться асинхронная запись.

У меня есть другая кнопка, которая открывает второе действие, которое отображает данные.

Второе действие использует ViewPager с фрагментом для каждой вкладки. Каждая вкладка имеет свой запрос.

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

Затем действие выполняет запросы, передавая каждый RealmResults к фрагменту, в котором RealmChangeListener будет установлен для отображения данных после загрузки. Может ли быть так, что RealmChangeListener не работает, когда фрагмент не присоединен к Activity?

Во всяком случае, это метод во фрагменте, который получает RealmResults (создано findAllAsyncSorted()) и предполагается обновить данные на адаптере:

public void updateData(OrderedRealmCollection<Bean> realmCollection) {
        Timber.v("Delegated data to fragment of adapter %s.", adapter);
        this.data = (RealmResults<Bean>) realmCollection;

    if (data.isLoaded()) {
        Timber.d("Data is already loaded on adapter %s.", adapter);
        adapter.updateDataManual(data);
    }

    if (!data.isValid()) {
        Timber.e("Data is not valid.");
    }


    listener = new RealmChangeListener<RealmResults<Bean>>() {
        @Override public void onChange(RealmResults<Bean> newResults) {
            Timber.v("Change listener for manual data triggered: %d results in fragment for category %s and adapter %s.",
                newResults.size(), category.toString(), adapter);

            adapter.updateDataManual(newResults);
        }

        @Override protected void finalize() throws Throwable {
            Timber.d("Finalizing change listener for adapter %s.", adapter);
            super.finalize();
        }
    };

    data.addChangeListener(listener);

    MyTimer.setRepeatingCallback(() -> {

        Timber.v("RealmResults in adapter %s are %s and %s, and the ChangeListener is %s.",
            adapter,
            data.isValid() ? "valid" : "invalid",
            data.isLoaded() ? "loaded" : "not loaded",
            listener);

        return true;
    }, 5000);
}

Как видите, я приложил усилия, чтобы убедиться, что запрос действителен и не загружен до тех пор, пока не будет добавлен прослушиватель изменений и что ни RealmResults ни RealmChangeListener сборка мусора.

Тем не менее, из четырех RealmChangeListeners, только два или менее (иногда ноль) триггера.

Обратите внимание, что это происходит только в том случае, если второе действие открывается вскоре после запуска асинхронной записи в MainActivity. Если я жду 2 секунды, все работает, как задумано. Я проверил, что RealmChangeListener не мусор, так как finalize() вызывается после выхода из приложения. Я понятия не имею, что может помешать слушателю работать. Есть ли что-то конкретное, на что я должен обратить внимание?

1 ответ

Вы должны иметь (сильную) ссылку на поле RealmResults<T> так что вы удерживаете его от получения GC'd.

Если RealmResults получает GC'd, то Realm больше не может автоматически обновлять его.

Другие вопросы по тегам