From 851ee81486cae0286ed021b5c808d81817540062 Mon Sep 17 00:00:00 2001 From: Viktor De Pasquale Date: Fri, 24 Jan 2020 17:52:31 +0100 Subject: [PATCH] Updated removing of "empty list" messages Before this commit, the loader removed messages _after_ it updated the list. Coincidentally the list updating mechanism is asynchronous to some extent and so slower devices might've had the message removed after changes have been dispatched which confused the recyclerview and caused the crash. Now, the loader is stripped of the responsibility update the list holding helper messages. The responsibility is for the user itself to notify listeners and then clear the helper list. This should hopefully delay the removal to the point where choreographer had enough time to traverse through the hierarchy. Stupid recycler view / layout managers. Literally unnecessary crash. --- .../topjohnwu/magisk/extensions/XBinding.kt | 65 ++++++++++++++++++- .../magisk/ui/module/ModuleViewModel.kt | 26 +++++--- 2 files changed, 82 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt b/app/src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt index c0c5c8dd1..cb496a4fa 100644 --- a/app/src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt +++ b/app/src/main/java/com/topjohnwu/magisk/extensions/XBinding.kt @@ -1,8 +1,71 @@ package com.topjohnwu.magisk.extensions +import androidx.databinding.ObservableList import com.topjohnwu.magisk.utils.KObservableField fun KObservableField.toggle() { value = !value -} \ No newline at end of file +} + +fun ObservableList.addOnListChangedCallback( + onChanged: ((sender: ObservableList) -> Unit)? = null, + onItemRangeRemoved: ((sender: ObservableList, positionStart: Int, itemCount: Int) -> Unit)? = null, + onItemRangeMoved: ((sender: ObservableList, fromPosition: Int, toPosition: Int, itemCount: Int) -> Unit)? = null, + onItemRangeInserted: ((sender: ObservableList, positionStart: Int, itemCount: Int) -> Unit)? = null, + onItemRangeChanged: ((sender: ObservableList, positionStart: Int, itemCount: Int) -> Unit)? = null +) = addOnListChangedCallback(object : ObservableList.OnListChangedCallback>() { + override fun onChanged(sender: ObservableList?) { + onChanged?.invoke(sender ?: return) + } + + override fun onItemRangeRemoved( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + onItemRangeRemoved?.invoke( + sender ?: return, + positionStart, + itemCount + ) + } + + override fun onItemRangeMoved( + sender: ObservableList?, + fromPosition: Int, + toPosition: Int, + itemCount: Int + ) { + onItemRangeMoved?.invoke( + sender ?: return, + fromPosition, + toPosition, + itemCount + ) + } + + override fun onItemRangeInserted( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + onItemRangeInserted?.invoke( + sender ?: return, + positionStart, + itemCount + ) + } + + override fun onItemRangeChanged( + sender: ObservableList?, + positionStart: Int, + itemCount: Int + ) { + onItemRangeChanged?.invoke( + sender ?: return, + positionStart, + itemCount + ) + } +}) \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt index 7a20c2db7..a461c520f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt @@ -13,6 +13,7 @@ import com.topjohnwu.magisk.core.tasks.RepoUpdater import com.topjohnwu.magisk.data.database.RepoByNameDao import com.topjohnwu.magisk.data.database.RepoByUpdatedDao import com.topjohnwu.magisk.databinding.ComparableRvItem +import com.topjohnwu.magisk.extensions.addOnListChangedCallback import com.topjohnwu.magisk.extensions.reboot import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.model.entity.internal.DownloadSubject @@ -156,6 +157,21 @@ class ModuleViewModel( } update(subject.module, progress.times(100).roundToInt()) } + + itemsInstalled.addOnListChangedCallback( + onItemRangeInserted = { sender, _, count -> + if (count > 0 || sender.size > 0) { + itemsInstalledHelpers.clear() + } + } + ) + itemsUpdatable.addOnListChangedCallback( + onItemRangeInserted = { sender, _, count -> + if (count > 0 || sender.size > 0) { + itemsUpdatableHelpers.clear() + } + } + ) } // --- @@ -175,19 +191,13 @@ class ModuleViewModel( .observeOn(AndroidSchedulers.mainThread()) .map { itemsInstalled.update(it.first, it.second) - if (itemsInstalled.isNotEmpty()) - itemsInstalledHelpers.remove(itemNoneInstalled) it.first } .observeOn(Schedulers.io()) .map { loadUpdates(it) } .map { it to itemsUpdatable.calculateDiff(it) } .observeOn(AndroidSchedulers.mainThread()) - .doOnSuccess { - itemsUpdatable.update(it.first, it.second) - if (itemsUpdatable.isNotEmpty()) - itemsUpdatableHelpers.remove(itemNoneUpdatable) - } + .doOnSuccess { itemsUpdatable.update(it.first, it.second) } .ignoreElement()!! @Synchronized @@ -261,7 +271,7 @@ class ModuleViewModel( @WorkerThread private fun List.loadDetail() = onEach { module -> Single.fromCallable { dao.getRepoById(module.item.id)!! } - .subscribeK { module.repo = it } + .subscribeK(onError = {}) { module.repo = it } .add() }