Compose State的各种转换

发布时间:2023年12月26日

普通值 转换为 State

很简单,就一个方法

val stringState = mutableStateOf("value")

但是也得注意,上面的方法是针对泛型的,如果只是基本数据类型,推荐使用相应的方法,在JVM上可以减少拆装箱带来的消耗

val intState = mutableIntStateOf(0)

State常用的几种使用方法

1.使用 MutableState 的对象,通过控制 MutableState 对象的 value 属性来获取和设置值

        val state1 = remember { mutableStateOf("") }
        TextField(state1.value, { state1.value = it })

?2.使用 MutableState 的解构声明,获取 value 和 setValue(高阶函数) 来使用

        val (value, setValue) = remember { mutableStateOf("") }
        TextField(value, setValue)

?

可以看到其声明,value 和 setValue 就对应 component1 和 component2 方法

3.使用属性代理

        var state3 by remember { mutableStateOf("") }
        TextField(state3, { state3 = it })

使用了 by 关键字,?这样?MutableState 对象的 getter 和 setter 就会被代理了,具体实现如下:?

LiveData 转换为 MutableState

/**
 * 将liveData放在compose中使用
 * ps:由于MutableLiveData是使用java写的,所以没有非空初始值的一定要声明为可空类型
 */
@Composable
fun <T : Any> MutableLiveData<T>.toMutableState(): MutableState<T> {
    val state = observeAsState() as State<T>
    return remember { MutableStateFromMutableLiveData(this, state) }
}

/**
 * creator: lt  lt.dygzs@qq.com
 * effect : 将[state]转换成[MutableState],[MutableState.value]的set会传递给[mutableLiveData]
 * warning:
 */
class MutableStateFromMutableLiveData<T : Any>(
    private val mutableLiveData: MutableLiveData<T>,
    private val state: State<T>
) :
    MutableState<T> {
    override var value: T
        get() = state.value
        set(value) {
            mutableLiveData.value = value
        }

    override fun component1(): T = value

    override fun component2(): (T) -> Unit = { value = it }
}

可以看到,我们创建了一个?MutableState 的子类?MutableStateFromMutableLiveData, 然后通过LiveData提供的api将其转为了State(不能修改的), 然后我们再监听?MutableStateFromMutableLiveData 的 value 的 setter 来修改 LiveData, 然后修改了 LiveData 的值后又会响应 State 的 value 的修改(其实也可以完全自定义实现?MutableState)

StateFlow 转换为 MutableState

和LiveData类似

/**
 * 将stateFlow放在compose中使用
 */
@Composable
fun <T> MutableStateFlow<T>.toMutableState(): MutableState<T> {
    val state = collectAsState()
    return remember { MutableStateFromMutableStateFlow(this, state) }
}

/**
 * creator: lt  lt.dygzs@qq.com
 * effect : 将[state]转换成[MutableState],[MutableState.value]的set会传递给[mutableStateFlow]
 * warning:
 */
class MutableStateFromMutableStateFlow<T>(
    private val mutableStateFlow: MutableStateFlow<T>,
    private val state: State<T>
) : MutableState<T> {
    override var value: T
        get() = state.value
        set(value) {
            mutableStateFlow.value = value
        }

    override fun component1(): T = value

    override fun component2(): (T) -> Unit = { value = it }
}

当然 Flow 也能转为 State, 但其为不可变的

SharedPreferences之类的 转换为 MutableState



/**
 * 将sp转为state,对state的操作会映射到对sp的操作
 */
@Composable
fun <T : Any> SpKey<T>.toMutableState(): MutableState<T> {
    return remember(this) {
        MutableStateFromSp(this)
    }
}

/**
 * creator: lt  2022/10/7  lt.dygzs@qq.com
 * effect : 将[state]转换成[MutableState],[MutableState.value]的set会传递给[mutableStateFlow]
 * warning:
 */
class MutableStateFromSp<T : Any>(
    private val sp: SpKey<T>,
) : MutableState<T> {
    override var value: T
        get() = sp.read()
        set(value) {
            field = value
            sp.write(value)
        }

    override fun component1(): T = value

    override fun component2(): (T) -> Unit = { value = it }
}

代码其实和上面的差不多,每次读取都会从 sp 中读取,而写入会同时写入到 sp 中(也可以自行添加缓存实现)

此代码不止可以用在 sp 上?

MutableState 转换为 Flow

MutableState 转换为 Flow 很简单,因为系统提供了相应的api

        var text by rememberMutableStateOf("")
        val flow = snapshotFlow {
            text
        }

这样每次 text 状态的改变,都会引起 flow 的回调

ps:响应的是监听的lambda的返回值

end

对Kotlin或KMP感兴趣的同学可以进Q群?101786950

如果这篇文章对您有帮助的话

可以扫码请我喝瓶饮料或咖啡(如果对什么比较感兴趣可以在备注里写出来)

文章来源:https://blog.csdn.net/qq_33505109/article/details/135227975
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。