Compose ViewModel State LiveData rememberSaveable

263 阅读1分钟

Compose ViewModel State LiveData rememberSaveable

根据官方提供lifecycle_version = "2.7.0"

// Lifecycles only (without ViewModel or LiveData)
implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version")
// LiveData
implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")
// Lifecycle utilities for Compose
implementation("androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version")
// ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
// ViewModel utilities for Compose
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version")
// Saved state module for ViewModel
implementation("androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version")
// optional - helpers for implementing LifecycleOwner in a Service
implementation("androidx.lifecycle:lifecycle-service:$lifecycle_version")
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")
// optional - ReactiveStreams support for LiveData
implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version")

State和LiveData方式

class HomeViewModel : ViewModel() {
    var name by mutableStateOf("button")
    var age = MutableLiveData<Int>()
    var users = MutableLiveData<List<UserBean>>()
    var userss = mutableStateListOf<UserBean>()
}
  • viewModel.name直接赋值方式
  • viewModel.age.postValue(age.asIntState().intValue.plus(10))LiveData post get特性赋值
  • var list =viewModel.users.asFlow().collectAsState(initial = emptyList<UserBean>())最终以 viewModel.users.postValue(listss)方式赋值
  • var list = viewModel.userss.toMutableStateList(),直接给list赋值,如果是toMutableList需要转为.toMutableStateList()

代码1

@Composable
fun HomeScreen(viewModel: HomeViewModel = HomeViewModel()) {
    Column(Modifier.fillMaxSize()) {
        var age = viewModel.age.asFlow().collectAsState(initial = 0)
        Row(Modifier.padding(horizontal = 12.dp)) {
            Button(onClick = {
                viewModel.name = "update button 2"
            }, Modifier.wrapContentSize()) {
                Text(text = viewModel.name)
            }
            Spacer(modifier = Modifier.width(15.dp))
            Button(onClick = {
                viewModel.age.postValue(age.asIntState().intValue.plus(10))
            }, Modifier.wrapContentSize()) {
                Text(text = "${age.asIntState().intValue}")
            }
        }
        var list = viewModel.users.asFlow().collectAsState(initial = emptyList<UserBean>())
        LazyColumn(
            Modifier.fillMaxSize(),
            contentPadding = PaddingValues(12.dp),
            verticalArrangement = Arrangement.spacedBy(5.dp)
        ) {
            if (list.value.isNullOrEmpty()) {
                item {
                    Box(contentAlignment = Alignment.Center) {
                        Text(text = "暂无数据")
                    }
                }
            } else {
                itemsIndexed(list.value!!) { index, bean ->
                    Row(
                        Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                            .background(Color.White, RoundedCornerShape(4.dp))
                            .shadow(
                                1.dp,
                                ambientColor = Color.LightGray,
                                spotColor = Color.LightGray
                            )
                            .clickable {
                                val size = viewModel.users.value?.size ?: 0
                                var listss = list.value.toMutableList()
                                listss.add(UserBean("测试$size", size + 20))
                                viewModel.users.postValue(listss)
                            }, verticalAlignment = Alignment.CenterVertically
                    ) {
                        Spacer(Modifier.width(15.dp))
                        Image(
                            imageVector = Icons.Filled.Face,
                            contentDescription = "avatar", contentScale = ContentScale.Inside,
                            modifier = Modifier
                                .size(32.dp)
                                .clip(
                                    RoundedCornerShape(16.dp)
                                )
                                .border(1.dp, Color.Magenta, RoundedCornerShape(16.dp))
                        )
                        Spacer(Modifier.width(15.dp))
                        Text(
                            text = "name ${bean.name} age ${bean.age}",
                            fontWeight = FontWeight.Medium
                        )
                    }
                }
            }
        }
        LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
            viewModel.name = "update button"
            val lists = mutableListOf<UserBean>().toMutableList()
            for (i in 0..10) {
                lists.add(UserBean("测试$i", i + 20))
            }
            viewModel.users.postValue(lists.toMutableStateList())
        }


    }

}

代码2

@Composable
fun HomeScreenS(viewModel: HomeViewModel = HomeViewModel()) {
    Column(Modifier.fillMaxSize()) {
        var list = viewModel.userss.toMutableStateList()
        LazyColumn(
            Modifier.fillMaxSize(),
            contentPadding = PaddingValues(12.dp),
            verticalArrangement = Arrangement.spacedBy(5.dp)
        ) {
            if (list.isNullOrEmpty()) {
                item {
                    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                        Text(text = "暂无数据")
                    }
                }
            } else {
                itemsIndexed(list) { index, bean ->
                    Card(
                        onClick = {
                            val size = list.size ?: 0
                            list.add(UserBean("测试$size", size + 20))
                        },
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(50.dp)
                    ) {
                        Text(text = "name ${bean.name} age ${bean.age}", Modifier.padding(15.dp))
                    }
                }
            }
        }
        LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
            viewModel.name = "update button"
            val lists = mutableListOf<UserBean>().toMutableList()
            for (i in 0..10) {
                lists.add(UserBean("测试$i", i + 20))
            }
            println("lists=" + lists.size)
            list = lists.toMutableStateList()
        }


    }

}

rememberSaveable方式

结合SavedStateHandle

调用viewModel: ConversationViewModel = ConversationViewModel(SavedStateHandle())

class ConversationViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue("Xi'an"))
    }
        private set

    fun update(newMessage: TextFieldValue) {
        message = newMessage
    }
}

stateSaver自定义

  • 方式1
val userSaver = run {
    val nameKey = "name"
    val ageKey = "age"
    mapSaver(
        save = { mapOf(nameKey to it.name, ageKey to it.age) },
        restore = { UserBean(it[nameKey] as String, it[ageKey] as Int) }
    )
}

data class UserBean(val name: String, val age: Int)

  • 引用1
val userState =
    rememberSaveable(stateSaver = userSaver) { mutableStateOf(UserBean("default", 0)) }
  • 方式2
data class Holder(var value: Int)

// this Saver implementation converts Holder object which we don't know how to save
// to Int which we can save
val HolderSaver = Saver<Holder, Int>(
    save = { it.value },
    restore = { Holder(it) }
)
  • 引用2
val holder = rememberSaveable(stateSaver = HolderSaver) { mutableStateOf(Holder(0)) }
  • 方式3
data class Size(val x: Int, val y: Int)

val sizeSaver = listSaver<Size, Int>(
    save = { listOf(it.x, it.y) },
    restore = { Size(it[0], it[1]) }
)
  • 引用3
var sizeY = rememberSaveable(stateSaver = sizeSaver) { mutableStateOf(Size(0, 0)) }
  • 常规用法
var showDetails by rememberSaveable { mutableStateOf(false) } 
val list = rememberSaveable { mutableListOf<Int>() }
  • 出处

developer.android.google.cn/jetpack/and… developer.android.google.cn/jetpack/com…

Screen_recording_20240218_112911 00_00_00-00_00_30.gif