Использование области с PublishSubject

Я хочу сопоставить результаты своей области с неизменяемой моделью представления и хочу прослушать изменения результатов, поэтому я испускаю их PublishSubject. Однако данные не отображаются в моем представлении recyclerview, пока я не поверну устройство, эта проблема исправлено, когда я удаляю observeOn(AndroidSchedulers.mainThread()).


Репозиторий:

fun notionsChanges(state: Boolean): Observable<Pair<MutableList<Notion>, OrderedCollectionChangeSet?>> {

        val notionsChanges = PublishSubject.create<Pair<MutableList<Notion>, OrderedCollectionChangeSet?>>()

        val realm = Realm.getDefaultInstance()
        val queryResult = realm.where<Notion>()
                .equalTo("isArchived", state)
                .findAllAsync()
        val listener: OrderedRealmCollectionChangeListener<RealmResults<Notion>> = OrderedRealmCollectionChangeListener { realmResults, changeSet ->
            if (realmResults.isValid && realmResults.isLoaded) {
                val results: MutableList<Notion> = realm.copyFromRealm(realmResults)
                notionsChanges.onNext(results to changeSet)
            }
        }
        queryResult.addChangeListener(listener)
        notionsChanges.doFinally {
            queryResult.removeChangeListener(listener)
            closeRealm(realm)
        }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())

        return notionsChanges
}

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

private var subscriptions: CompositeDisposable = CompositeDisposable()

override fun onResume() {
    super.onResume()
    showData()
}

override fun onPause() {
    subscriptions.clear()
    super.onPause()
}

private fun showData() {
        val viewModel = present(idleStates, resources, isIdle)
        with(viewModel) {
            subscriptions.addAll(
                    notionsChanges.subscribe(notionsAdapter::handleChanges),
                    //other subscriptions.
            )
        }
}

notionsAdapter.handleChanges:

fun handleChanges(collectionChange: Pair<List<NotionCompactViewModel>, OrderedCollectionChangeSet?>) {
    val (collection, changeset) = collectionChange
    debug("${collection.size}") //correctly prints the actual size of the collection.
    replaceAll(collection)
    if (changeset == null)
        notifyDataSetChanged()
    else {
        for (change in changeset.changeRanges)
            notifyItemRangeChanged(change.startIndex, change.length)

        for (insertion in changeset.insertionRanges)
            notifyItemRangeInserted(insertion.startIndex, insertion.length)

        for (deletion in changeset.deletionRanges)
            notifyItemRangeRemoved(deletion.startIndex, deletion.length)
    }
}

извините, если код неясен.


редактировать: мой onBindViewHolder иногда не вызывается (конечно, когда recyclerview пуст).


person mhashim6    schedule 05.09.2018    source источник
comment
Настоящий сюрприз в том, что это вообще работает. findAllAsync и addChangeListener не поддерживаются в потоках без цикла, это должно выполняться в планировщике, созданном из цикла HandlerThread.   -  person EpicPandaForce    schedule 06.09.2018
comment
даже если я звоню из основного потока?   -  person mhashim6    schedule 06.09.2018
comment
А, твой subscribeOn(io()) обманул меня. Тогда это просто небезопасно для больших наборов данных. Упс! Вы уверены, что вместо этого не следует использовать BehaviorSubject?   -  person EpicPandaForce    schedule 06.09.2018
comment
то, чего я пытался добиться, - это получить результаты в основном потоке, затем обработать их в фоновом режиме, а затем отобразить их в основном потоке.   -  person mhashim6    schedule 06.09.2018
comment
Я попробовал BehaviorSubject, но он показал такое же поведение.   -  person mhashim6    schedule 06.09.2018
comment
Я сделал это, потому что, когда я попробовал это решение, возникла та же проблема.   -  person mhashim6    schedule 06.09.2018
comment
Держать на секунду. Вы используете Realm 5.0+? Набор изменений больше не может быть обнулён. Вы получаете state == INITIAL.   -  person EpicPandaForce    schedule 06.09.2018
comment
да, область v5.4.2.   -  person mhashim6    schedule 06.09.2018
comment
Еще раз, Вы ответили на мой вопрос, пожалуйста, опубликуйте это в ответе, спасибо! Кроме того, если вы не возражаете, является ли этот подход хорошим способом добиться того, что я пытался сделать?   -  person mhashim6    schedule 06.09.2018
comment
Технически это имеет смысл, но использование copyFromRealm() в потоке пользовательского интерфейса может вызвать ANR с большим набором данных, поэтому я рекомендовал HandlerThread в другом ответе, который вы связали.   -  person EpicPandaForce    schedule 06.09.2018
comment
Да, это то, что я использую прямо сейчас, теперь, когда исходная проблема (с changeSet) решена, ваше другое решение с чистой архитектурой тоже работает, еще раз спасибо.   -  person mhashim6    schedule 06.09.2018


Ответы (1)


Начиная с Realm 5.0, начальный набор изменений больше не сигнализируется с помощью changeset == null.

Вам необходимо проверить:

if(changeSet.getState() == State.INITIAL) {
    adapter.notifyDataSetChanged() 
person EpicPandaForce    schedule 05.09.2018