大气的网站模板,查询网站服务器,制作网站要花多少钱如何,钓鱼网站盗号下载前言
在Compose的学习中#xff0c;我们在可组合函数中使用rememberSaveable保存应用数据#xff0c;但这可能意味着将逻辑保留在可组合函数中或附近。随着应用体量不断变大#xff0c;您应将数据和逻辑从可组合函数中移出。
而在之前的应用架构学习中…前言
在Compose的学习中我们在可组合函数中使用rememberSaveable保存应用数据但这可能意味着将逻辑保留在可组合函数中或附近。随着应用体量不断变大您应将数据和逻辑从可组合函数中移出。
而在之前的应用架构学习中我们接触到了MVVM架构他将应用数据存储在了ViewModel中它是Android Jetpack 库中的架构组件之一。
当框架在配置更改或其他事件期间销毁并重新创建 activity 时存储的数据不会丢失。不过如果 activity 因进程终止而被销毁数据将会丢失。ViewModel 只能通过快速重新创建 activity 缓存数据。
了解应用架构
架构原则
最常用的架构原则包括分离关注点和通过模型驱动界面。
分离关注点该原则指出应将应用分为函数类每个类有各自的职责通过模型驱动界面该原则指出应该通过模型驱动界面最好是持久性模型 模型是负责处理应用数据的组件。它们独立于应用中的界面元素和应用组件因此不受应用的生命周期以及相关的关注点的影响。 推荐的应用架构
基于上面两点原则每个应用应至少有两个层
界面层屏幕上显示应用数据但独立于数据层的层数据层用于存储、检索和提供应用数据的层
每当数据因用户互动例如按了某个按钮而发生变化时界面都应随之更新以反映这些变化。
界面层由以下组件组成
界面元素用于在屏幕上呈现数据的组件。您将使用 Compose 构建这些元素。状态容器用于保存数据、向界面提供数据以及处理应用逻辑的组件。此处我们使用 ViewModel ViewModel
简介
ViewModel组件用于存储和公开界面所使用的状态UI State。
界面状态UI State是经过ViewModel转换的应用数据。界面UI是相对于用户而言的界面状态是相对于应用而言的例如一个开关switch展现在用户面前而switch是开还是关就是switch的界面状态。因此对于界面状态的任何改变都会直接影响界面。
ViewModel会存储应用相关的数据这些数据不会在activity被销毁并重新创建时被销毁。应用会在配置更改期间自动保留ViewModel对象以便在重组时ViewModel存储的数据可以立即被使用。
与Compose梦幻联动
在使用Compose时ViewModel是向可组合项展示界面状态的主要方式。过去我们将数据的存储和处理方式留在activity或fragment中臃肿而不直观如今在混合应用中activity和fragment仅用于托管可组合函数。
添加ViewModel
以下是用户掷骰子屏幕的 ViewModel 实现示例。
1. 打开app模块下的build.gradle.kts在dependencies块添加如下内容
dependencies {
// other dependenciesimplementation(androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1)
//...
}
2. 添加一个数据类存储各项值并创建一个类继承ViewModel
//数据类存储游戏的值
data class DiceUiState(val firstDieValue: Int? null,val secondDieValue: Int? null,val numberOfRolls: Int 0,
)class DiceRollViewModel : ViewModel() {// 展示界面状态// 此处的StateFlow是数据容器式可观察数据流其value属性反映了当前的状态值// 有了它可组合函数就可以监听界面状态更新//防止外部类修改ViewModel的数据设置为private同时val类型不包含setter为只读属性private val _uiState MutableStateFlow(DiceUiState())//asStateFlow方法使可变状态流变为只读状态流界面通过只读属性的uiState读取值val uiState: StateFlowDiceUiState _uiState.asStateFlow()// 处理业务逻辑fun rollDice() {_uiState.update { currentState -//调用 copy 方法来创建新的 DiceState 对象并将其赋值给 uiState 变量。//这将触发 UI 的重新渲染。currentState.copy(firstDieValue Random.nextInt(from 1, until 7),secondDieValue Random.nextInt(from 1, until 7),numberOfRolls currentState.numberOfRolls 1,)}}
}3. 从activity访问ViewModel
//Compose写法
import androidx.lifecycle.viewmodel.compose.viewModel// Use the viewModel() function from the lifecycle-viewmodel-compose artifact
Composable
fun DiceRollScreen(viewModel: DiceRollViewModel viewModel()
) {val uiState by viewModel.uiState.collectAsStateWithLifecycle()// Update UI elements
}//Kotlin写法
import androidx.activity.viewModelsclass DiceRollActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {// 在系统第一次调用Activity的onCreate()方法时创建一个 ViewModel实例// 重新创建的activity会收到相同的、第一次创建activity时留下的ViewModel实例// 此处使用了by viewModels()的Kotlin属性委托// 他创建并初始化与activity相关联的ViewModelval viewModel: DiceRollViewModel by viewModels()lifecycleScope.launch {repeatOnLifecycle(Lifecycle.State.STARTED) {viewModel.uiState.collect {// 在此处更新ui元素}}}}
}ViewModel的生命周期
ViewModel的生命周期与其作用域直接相关。作用域指的是ViewModel处理的组件如activity、fragment、navigation。
以 activity为例当进入onCreate方法ViewModel的生命周期随之开始而进入onDestroy方法、activity即将被销毁时ViewModel也进入了它生命周期的最后一个方法onCleared方法。 ViewModel会一直保存在内存中直到其作用域ViewModelStoreOwner消失。这使得 ViewModels 成为了存储在配置更改后仍然存在的数据的绝佳解决方案。
清除 ViewModel 依赖项
当 ViewModelStoreOwner 在 ViewModel 的生命周期内销毁 ViewModel 时ViewModel 会调用 onCleared 方法。这样您就可以清理遵循 ViewModel 生命周期的任何工作或依赖项。
以广播接收器为例我们可以重写onClear方法以注销它
class TestViewModel(context: Application) : AndroidViewModel(context) {private var receiver : BroadcastReceiver ? null...override fun onCleared() {super.onCleared()receiver?.unregister()}
}