Remove usage of BindingCollectionAdapter (part 2)

This commit is contained in:
topjohnwu 2022-06-02 23:40:10 -07:00
parent 6305159c5e
commit 5471147422
9 changed files with 186 additions and 42 deletions

View File

@ -78,10 +78,6 @@ dependencies {
implementation("dev.rikka.rikkax.recyclerview:recyclerview-ktx:1.3.1")
implementation("io.noties.markwon:core:4.6.2")
val vBAdapt = "4.0.0"
val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter"
implementation("${bindingAdapter}:${vBAdapt}")
val vLibsu = "5.0.2"
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
implementation("com.github.topjohnwu.libsu:service:${vLibsu}")

View File

@ -8,10 +8,7 @@ import android.text.Spanned
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.*
import androidx.annotation.DrawableRes
import androidx.appcompat.widget.Toolbar
import androidx.cardview.widget.CardView
@ -295,3 +292,8 @@ fun TextView.setTextColorAttr(attr: Int) {
fun TextView.setText(text: TextHolder) {
this.text = text.getText(context.resources)
}
@BindingAdapter("items", "layout")
fun Spinner.setAdapter(items: Array<Any>, layoutRes: Int) {
adapter = ArrayAdapter(context, layoutRes, items)
}

View File

@ -0,0 +1,162 @@
package com.topjohnwu.magisk.databinding
import androidx.databinding.ListChangeRegistry
import androidx.databinding.ObservableList
import androidx.databinding.ObservableList.OnListChangedCallback
import java.util.*
@Suppress("UNCHECKED_CAST")
class MergeObservableList<T> : AbstractList<T>(), ObservableList<T> {
private val lists: MutableList<List<T>> = mutableListOf()
private val listeners = ListChangeRegistry()
private val callback = Callback<T>()
override fun addOnListChangedCallback(callback: OnListChangedCallback<out ObservableList<T>>) {
listeners.add(callback)
}
override fun removeOnListChangedCallback(callback: OnListChangedCallback<out ObservableList<T>>) {
listeners.remove(callback)
}
override fun get(index: Int): T {
if (index < 0)
throw IndexOutOfBoundsException()
var idx = index
for (list in lists) {
val size = list.size
if (idx < size) {
return list[idx]
}
idx -= size
}
throw IndexOutOfBoundsException()
}
override val size: Int
get() = lists.fold(0) { i, it -> i + it.size }
fun insertItem(obj: T): MergeObservableList<T> {
val idx = size
lists.add(listOf(obj))
++modCount
listeners.notifyInserted(this, idx, 1)
return this
}
fun insertList(list: ObservableList<out T>): MergeObservableList<T> {
val idx = size
lists.add(list)
++modCount
(list as ObservableList<T>).addOnListChangedCallback(callback)
if (list.isNotEmpty())
listeners.notifyInserted(this, idx, list.size)
return this
}
fun removeItem(obj: T): Boolean {
var idx = 0
for ((i, list) in lists.withIndex()) {
if (list !is ObservableList<*>) {
if (obj == list[0]) {
lists.removeAt(i)
++modCount
listeners.notifyRemoved(this, idx, 1)
return true
}
}
idx += list.size
}
return false
}
fun removeList(listToRemove: ObservableList<out T>): Boolean {
var idx = 0
for ((i, list) in lists.withIndex()) {
if (listToRemove === list) {
(list as ObservableList<T>).removeOnListChangedCallback(callback)
lists.removeAt(i)
++modCount
listeners.notifyRemoved(this, idx, list.size)
return true
}
idx += list.size
}
return false
}
override fun clear() {
val sz = size
for (list in lists) {
if (list is ObservableList<*>) {
(list as ObservableList<T>).removeOnListChangedCallback(callback)
}
}
++modCount
lists.clear()
if (sz > 0)
listeners.notifyRemoved(this, 0, sz)
}
private fun subIndexToIndex(subList: List<*>, index: Int): Int {
if (index < 0)
throw IndexOutOfBoundsException()
var idx = 0
for (list in lists) {
if (subList === list) {
return idx + index
}
idx += list.size
}
throw IllegalArgumentException()
}
inner class Callback<T> : OnListChangedCallback<ObservableList<T>>() {
override fun onChanged(sender: ObservableList<T>) {
++modCount
listeners.notifyChanged(this@MergeObservableList)
}
override fun onItemRangeChanged(
sender: ObservableList<T>,
positionStart: Int,
itemCount: Int
) {
listeners.notifyChanged(this@MergeObservableList,
subIndexToIndex(sender, positionStart), itemCount)
}
override fun onItemRangeInserted(
sender: ObservableList<T>,
positionStart: Int,
itemCount: Int
) {
++modCount
listeners.notifyInserted(this@MergeObservableList,
subIndexToIndex(sender, positionStart), itemCount)
}
override fun onItemRangeMoved(
sender: ObservableList<T>,
fromPosition: Int,
toPosition: Int,
itemCount: Int
) {
val idx = subIndexToIndex(sender, 0)
listeners.notifyMoved(this@MergeObservableList,
idx + fromPosition, idx + toPosition, itemCount)
}
override fun onItemRangeRemoved(
sender: ObservableList<T>,
positionStart: Int,
itemCount: Int
) {
++modCount
listeners.notifyRemoved(this@MergeObservableList,
subIndexToIndex(sender, positionStart), itemCount)
}
}
}

View File

@ -4,6 +4,7 @@ import android.content.Context
import androidx.core.net.toUri
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.*
@ -23,7 +24,6 @@ import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.BR
import kotlin.math.roundToInt
enum class MagiskState {

View File

@ -10,6 +10,7 @@ import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.model.module.LocalModule
import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.databinding.MergeObservableList
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.diffListOf
@ -21,7 +22,6 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
class ModuleViewModel : BaseViewModel() {

View File

@ -15,6 +15,7 @@ import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.MergeObservableList
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.diffListOf
import com.topjohnwu.magisk.events.SnackbarEvent
@ -27,7 +28,6 @@ import com.topjohnwu.magisk.view.TextItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
class SuperuserViewModel(
private val db: PolicyDao

View File

@ -34,7 +34,6 @@ import com.topjohnwu.magisk.ktx.getLabel
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.Utils
import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.ItemBinding
import java.util.concurrent.TimeUnit.SECONDS
class SuRequestViewModel(
@ -70,8 +69,6 @@ class SuRequestViewModel(
false
}
val itemBinding = ItemBinding.of<String>(BR.item, R.layout.item_spinner)
private val handler = SuRequestHandler(AppContext.packageManager, policyDB)
private lateinit var timer: CountDownTimer
private var initialized = false

View File

@ -5,8 +5,6 @@
<data>
<import type="java.util.Arrays"/>
<variable
name="viewModel"
type="com.topjohnwu.magisk.ui.surequest.SuRequestViewModel" />
@ -101,8 +99,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:enabled="@{viewModel.grantEnabled}"
app:items="@{Arrays.asList(@stringArray/allow_timeout)}"
app:itemBinding="@{viewModel.itemBinding}"
app:items="@{@stringArray/allow_timeout}"
app:layout="@{@layout/item_spinner}"
android:selection="@={viewModel.selectedItemPosition}" />
<TextView

View File

@ -1,25 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable name="item" type="String" />
</data>
<TextView
style="?android:attr/spinnerItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:background="?colorSurfaceSurfaceVariant"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:singleLine="true"
android:text="@{item}"
android:textAlignment="inherit"
tools:text="Forever" />
</layout>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="?android:attr/spinnerItemStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:background="?colorSurfaceSurfaceVariant"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:singleLine="true"
android:textAlignment="inherit"
tools:text="Forever" />