- #每天一个知识点#
Jetpack Compose无状态组件示例代码和解释
Jetpack Compose无状态组件不自带任何状态,状态由外部传入、事件回调向外抛出,UI只负责根据入参渲染,是可复用、易测试的纯UI单元,CMP跨平台组件优先推荐这种写法。
```kotlin
@Composable
fun CounterView(count: Int, onAddClick: () -> Unit) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "计数:$count", fontSize = 22.sp)
Button(onClick = onAddClick) { Text("点我+1") }
}
}
```
该组件内部没有remember、mutableStateOf,自身不保存数据。count作为只读入参,UI完全随传入值变化;点击动作不处理计数逻辑,仅回调onAddClick交给上层。上层可以是remember本地状态,也可以是ViewModel的StateFlow,组件本身和状态来源解耦。
无状态组件特点:输入相同参数,渲染结果一定相同,符合纯函数思想;方便预览、单元测试,多页面复用不会互相干扰。它只承担视图展示职责,状态和业务交由父层托管,和有状态组件搭配使用:上层做状态持有,下层大量封装无状态UI控件,这是Compose标准分层范式。相比内部带remember的有状态组件,无状态组件可控性更强,跨端维护成本更低。1 赞 · 0 评论 - #每天一个知识点#
Jetpack Compose配合ViewModel托管状态,可解决remember在屏幕旋转、配置变更后状态丢失问题,实现UI与业务解耦,也是CMP跨平台标准实践。ViewModel生命周期独立于Compose页面,配置变更不会销毁实例,依靠viewModelScope安全执行协程。
```kotlin
class CounterVM : ViewModel() {
private val _count = MutableStateFlow(0)
val count = _count.asStateFlow()
fun add() { _count.value += 1 }
}
@Composable
fun CounterScreen(vm: CounterVM = viewModel()) {
val count by vm.count.collectAsStateWithLifecycle()
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "计数:$count", fontSize = 22.sp)
Button(onClick = { vm.add() }) { Text("点我+1") }
}
}
```
1. MutableStateFlow:可变状态源,私有封装,禁止外部直接修改;asStateFlow对外只暴露只读流,遵循单向数据流。
2. collectAsStateWithLifecycle:带生命周期感知的订阅,页面后台自动暂停收集,节约资源、防止内存泄漏,优于collectAsState。
3. viewModel():获取ViewModel实例,页面重组复用同一个对象,Activity重建仍保留数据。
4. 业务逻辑全部收拢在VM,Composable只负责订阅状态、渲染UI、转发点击事件,UI层不存业务数据。
对比remember本地状态:remember适合组件内部临时轻量状态;ViewModel适合页面级业务数据、接口请求、需要跨配置保留的状态。![[玫瑰]](//lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_103.6c2eed8.png)
![[玫瑰]](//lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_103.6c2eed8.png)
1 赞 · 0 评论 - #每天一个知识点#
jetpack compose 的有状态示例代码和解析
Jetpack Compose 采用声明式UI,有状态组件核心是状态驱动界面,状态变更自动重组UI,区别于传统View手动刷新。Compose遵循单向状态流,状态尽量上提,由可信数据源持有,UI仅订阅展示,避免状态分散难以维护。
```kotlin
@Composable
fun CounterScreen() {
// remember:组合内保存状态,重组不丢失;mutableStateOf:创建可观察状态
var count by remember { mutableStateOf(0) }
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = "计数:$count", fontSize = 22.sp)
Button(onClick = { count++ }) {
Text("点我+1")
}
}
}
```
1. mutableStateOf(0) :生成可观察State,是状态载体,值变化会触发订阅该状态的Composable重组。
2. remember {} :记忆函数,绑定到当前组合树节点。界面正常重组(如旋转、重组刷新)时,remember缓存状态,不会反复初始化;页面销毁移除组合树,状态随之清空。
3. by 委托语法:简化 .value 读写,直接读写count等价于state.value。
4. 缺陷:该状态是本地内部状态,仅当前组件持有。屏幕配置变更(旋转Activity),Activity重建,remember状态丢失,无法跨配置持久化。
如果需要旋转保状态,要把状态抽至ViewModel,ViewModel生命周期独立于页面,配置变更不会销毁,搭配StateFlow对外暴露只读状态,实现业务与UI解耦,也是CMP跨平台推荐写法。
本地remember适合轻量临时状态,ViewModel承载页面业务状态,二者分工明确,是Compose状态管理最基础的两套方案。![[玫瑰]](//lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_103.6c2eed8.png)
![[玫瑰]](//lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_103.6c2eed8.png)
1 赞 · 0 评论
![[玫瑰]](http://lf-web-assets.juejin.cn/obj/juejin-web/xitu_juejin_web/img/jj_emoji_103.6c2eed8.png)