mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-22 10:18:30 +00:00
Cleanup filterable list implementation
This commit is contained in:
parent
d130aa02a1
commit
382568bd3c
@ -1,55 +1,38 @@
|
|||||||
package com.topjohnwu.magisk.databinding
|
package com.topjohnwu.magisk.databinding
|
||||||
|
|
||||||
import android.os.Handler
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import android.os.HandlerThread
|
import kotlinx.coroutines.Dispatchers
|
||||||
import android.os.Looper
|
import kotlinx.coroutines.Job
|
||||||
import java.util.*
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.Collections
|
||||||
|
|
||||||
class FilterableDiffObservableList<T>(
|
class FilterableDiffObservableList<T>(
|
||||||
callback: Callback<T>
|
callback: Callback<T>,
|
||||||
|
private val scope: CoroutineScope
|
||||||
) : DiffObservableList<T>(callback) {
|
) : DiffObservableList<T>(callback) {
|
||||||
|
|
||||||
var filter: ((T) -> Boolean)? = null
|
private var sublist: MutableList<T> = list
|
||||||
set(value) {
|
private var job: Job? = null
|
||||||
field = value
|
|
||||||
queueUpdate()
|
|
||||||
}
|
|
||||||
@Volatile
|
|
||||||
private var sublist: MutableList<T> = super.list
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
private val ui by lazy { Handler(Looper.getMainLooper()) }
|
fun filter(filter: (T) -> Boolean) {
|
||||||
private val handler = Handler(HandlerThread("List${hashCode()}").apply { start() }.looper)
|
job?.cancel()
|
||||||
private val updater = Runnable {
|
job = scope.launch(Dispatchers.Default) {
|
||||||
val filter = filter ?: { true }
|
val newList = list.filter(filter)
|
||||||
val newList = super.list.filter(filter)
|
|
||||||
val diff = synchronized(this) { doCalculateDiff(sublist, newList) }
|
val diff = synchronized(this) { doCalculateDiff(sublist, newList) }
|
||||||
ui.post {
|
withContext(Dispatchers.Main) {
|
||||||
sublist = Collections.synchronizedList(newList)
|
sublist = Collections.synchronizedList(newList)
|
||||||
diff.dispatchUpdatesTo(listCallback)
|
diff.dispatchUpdatesTo(listCallback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun queueUpdate() {
|
|
||||||
handler.removeCallbacks(updater)
|
|
||||||
handler.post(updater)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasFilter() = filter != null
|
|
||||||
|
|
||||||
fun filter(switch: (T) -> Boolean) {
|
|
||||||
filter = switch
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reset() {
|
|
||||||
filter = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
override fun get(index: Int): T {
|
override fun get(index: Int): T {
|
||||||
return sublist.get(index)
|
return sublist[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun add(element: T): Boolean {
|
override fun add(element: T): Boolean {
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.databinding
|
package com.topjohnwu.magisk.databinding
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
||||||
fun <T : AnyDiffRvItem> diffListOf() =
|
fun <T : AnyDiffRvItem> diffListOf() =
|
||||||
DiffObservableList(DiffRvItem.callback<T>())
|
DiffObservableList(DiffRvItem.callback<T>())
|
||||||
|
|
||||||
fun <T : AnyDiffRvItem> filterableListOf() =
|
fun <T : AnyDiffRvItem> filterableListOf(scope: CoroutineScope) =
|
||||||
FilterableDiffObservableList(DiffRvItem.callback<T>())
|
FilterableDiffObservableList(DiffRvItem.callback<T>(), scope)
|
||||||
|
@ -15,8 +15,8 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
|
|
||||||
class RvItemAdapter<T: RvItem>(
|
class RvItemAdapter<T: RvItem>(
|
||||||
internal val items: List<T>,
|
val items: List<T>,
|
||||||
private val extraBindings: SparseArray<*>?
|
val extraBindings: SparseArray<*>?
|
||||||
) : RecyclerView.Adapter<RvItemAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<RvItemAdapter.ViewHolder>() {
|
||||||
|
|
||||||
private var lifecycleOwner: LifecycleOwner? = null
|
private var lifecycleOwner: LifecycleOwner? = null
|
||||||
@ -113,7 +113,8 @@ inline fun bindExtra(body: (SparseArray<Any?>) -> Unit) = SparseArray<Any?>().al
|
|||||||
@BindingAdapter("items", "extraBindings", requireAll = false)
|
@BindingAdapter("items", "extraBindings", requireAll = false)
|
||||||
fun <T: RvItem> RecyclerView.setAdapter(items: List<T>?, extraBindings: SparseArray<*>?) {
|
fun <T: RvItem> RecyclerView.setAdapter(items: List<T>?, extraBindings: SparseArray<*>?) {
|
||||||
if (items != null) {
|
if (items != null) {
|
||||||
if ((adapter as? RvItemAdapter<T>)?.items !== items) {
|
val rva = (adapter as? RvItemAdapter<*>)
|
||||||
|
if (rva == null || rva.items !== items || rva.extraBindings !== extraBindings) {
|
||||||
adapter = RvItemAdapter(items, extraBindings)
|
adapter = RvItemAdapter(items, extraBindings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.deny
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
|
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
import com.topjohnwu.magisk.arch.AsyncLoadViewModel
|
||||||
import com.topjohnwu.magisk.core.di.AppContext
|
import com.topjohnwu.magisk.core.di.AppContext
|
||||||
@ -37,7 +38,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
|||||||
query()
|
query()
|
||||||
}
|
}
|
||||||
|
|
||||||
val items = filterableListOf<DenyListRvItem>()
|
val items = filterableListOf<DenyListRvItem>(viewModelScope)
|
||||||
val extraBindings = bindExtra {
|
val extraBindings = bindExtra {
|
||||||
it.put(BR.viewModel, this)
|
it.put(BR.viewModel, this)
|
||||||
}
|
}
|
||||||
@ -68,7 +69,7 @@ class DenyListViewModel : AsyncLoadViewModel() {
|
|||||||
query()
|
query()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun query() {
|
private fun query() {
|
||||||
items.filter {
|
items.filter {
|
||||||
fun filterSystem() = isShowSystem || !it.info.isSystemApp()
|
fun filterSystem() = isShowSystem || !it.info.isSystemApp()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user