简体   繁体   English

为什么我们不能在 jetpack compose 的 mutableStateListOf 中使用委托属性

[英]Why we cannot use delegate property in mutableStateListOf in jetpack compose

I want to know that why we cannot use delegate property in mutableStateListOf .我想知道为什么我们不能在mutableStateListOf中使用委托属性。 When I am trying to add当我试图添加

val favourites by remember { mutableStateListOf<Int>() }

It gives me error它给我错误

Type 'TypeVariable(T)' has no method 'getValue(Nothing?, KProperty<*>)' and thus it cannot serve as a delegate

Also I tried to imports我也试过进口

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

but it stills gives the same error.但它仍然给出同样的错误。 Is there any specific reason for this?这有什么具体原因吗? Thanks谢谢

What you should be asking is how do i use mutableStateOf with delegation because delagation is not part of any class by default.您应该问的是我如何将mutableStateOf与委托一起使用,因为默认情况下延迟不是任何 class 的一部分。

MutableState delegation is implemented as MutableState 委托实现为

/**
 * Permits property delegation of `val`s using `by` for [State].
 *
 * @sample androidx.compose.runtime.samples.DelegatedReadOnlyStateSample
 */
@Suppress("NOTHING_TO_INLINE")
inline operator fun <T> State<T>.getValue(thisObj: Any?, property: KProperty<*>): T = value

/**
 * Permits property delegation of `var`s using `by` for [MutableState].
 *
 * @sample androidx.compose.runtime.samples.DelegatedStateSample
 */
@Suppress("NOTHING_TO_INLINE")
inline operator fun <T> MutableState<T>.setValue(thisObj: Any?, property: KProperty<*>, value: T) {
    this.value = value
}

/**
 * A mutable value holder where reads to the [value] property during the execution of a [Composable]
 * function, the current [RecomposeScope] will be subscribed to changes of that value. When the
 * [value] property is written to and changed, a recomposition of any subscribed [RecomposeScope]s
 * will be scheduled. If [value] is written to with the same value, no recompositions will be
 * scheduled.
 *
 * @see [State]
 * @see [mutableStateOf]
 */
@Stable
interface MutableState<T> : State<T> {
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

Functions you import with您导入的函数

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

are getValue and setValue functions in snippet above.是上面代码段中的getValuesetValue函数。

You can create delegation functions for classes as extension functions which require you to import them or as part of class as in examples below.您可以为类创建委托函数作为需要导入它们的扩展函数,或者作为 class 的一部分,如下例所示。

class CalculateDelegate {

    private var calculatedProperty = 0

    operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        return calculatedProperty
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        calculatedProperty = value * 2
    }

}

/**
 * Delegate [CalculateDelegate] to this function
 */
fun delegateCalculationFunction() = CalculateDelegate()

If you create a instances using如果您使用创建实例

var delegatedNum1 by CalculateDelegate()
var delegatedNum2 by delegateCalculationFunction()

And then if you change or call setValue as然后,如果您将 setValue 更改或调用为

delegatedNum1 = 4
delegatedNum2 = 3

if you print these delegateNum1, and delegateNum2 you will see that they are 8 and 6 because of overriding setValue如果您打印这些 delegateNum1 和 delegateNum2,您将看到它们是 8 和 6,因为覆盖了setValue

If you wish to force overriding setValue and getValue functions for a class you can use ReadWriteProperty as如果您希望强制覆盖 class 的 setValue 和 getValue 函数,您可以使用 ReadWriteProperty 作为

public interface ReadWriteProperty<in T, V> : ReadOnlyProperty<T, V> {
    /**
     * Returns the value of the property for the given object.
     * @param thisRef the object for which the value is requested.
     * @param property the metadata for the property.
     * @return the property value.
     */
    public override operator fun getValue(thisRef: T, property: KProperty<*>): V

    /**
     * Sets the value of the property for the given object.
     * @param thisRef the object for which the value is requested.
     * @param property the metadata for the property.
     * @param value the value to set.
     */
    public operator fun setValue(thisRef: T, property: KProperty<*>, value: V)
}

Then you need to override getValue and setValue functions.然后您需要重写getValuesetValue函数。

class CalculateDelegate: ReadWriteProperty<Any?, Int> {

    private var calculatedProperty = 0

    override operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
        return calculatedProperty
    }

    override operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
        calculatedProperty = value * 2
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM