当前位置: 首页 > news >正文

做软件项目需不需要有网站厦门关键词排名提升

做软件项目需不需要有网站,厦门关键词排名提升,诸葛企业网站建设公司,电商网站用php做的吗在使用Compose定义UI界面时#xff0c;可以发现界面的变换往往与Compose组件内部的状态相关#xff0c;当状态值发生变化时#xff0c;Compose构成的可组合的界面也会刷新发生相应的变化。将在本笔记中将对可组合项的状态的定义、状态提升、状态丢失和状态的保存进行简单介绍…在使用Compose定义UI界面时可以发现界面的变换往往与Compose组件内部的状态相关当状态值发生变化时Compose构成的可组合的界面也会刷新发生相应的变化。将在本笔记中将对可组合项的状态的定义、状态提升、状态丢失和状态的保存进行简单介绍。。 一、什么是可组合项的状态 Compose采用了单向数据流设计思想。定义界面的可组合函数本身没有任何返回值也没有像类一样封装内部的私有状态。因此通过定义可组合函数的状态使得可组合函数关联的界面可以观察是否发生了变化。 在Kotlin语言中定义了一个接口MutableState代码如下 interface MutableState : State { override var value: T } 实现MutableState接口的任何类型的对象就是一个状态状态是可变的每个状态中保存一个value值。在执行可组合函数期间读取 value 属性。如果value属性值发生了变化则可组合函数会发生重构如果value属性值没有变化则不会产生可组合函数的重构。 Compose组件可以通过mutableStateOf函数来获得一个这样的状态对象。例如 val someState mutableStateOf(true) 例如在上述的定义中 someState就会被解析为一个可以存储Boolean布尔真值的可变状态值。 Android结合remember API可以将状态值保存到内存中当在内存中记住这个状态值。这样的好处就是系统会在初始组合期间将由 remember 计算的值存储在组合中并在重组期间返回存储的值。当remember和状态值结合会非常容易对可组合函数的重构产生作用因为remember记住的状态值在内存中。当然remember不仅仅与可变的状态值组合也可以与非可变值组合。 在可组合项中声明 MutableState 对象的方法有三种 val mutableState remember { mutableStateOf(default) } var value by remember { mutableStateOf(default) } val (value, setValue) remember{ mutableStateOf(default) } 1.方式一:val mutableState remember { mutableStateOf(default) } 这种方式是直接通过状态的引用来获取或设置value属性值 需要导入 import androidx.compose.runtime.remember 示例代码如下 Preview Composable fun CountScreen(){val counterState remember{mutableStateOf(0)}Column(modifier Modifier.fillMaxSize(),horizontalAlignment Alignment.CenterHorizontally,verticalArrangement Arrangement.Center){//引用状态值Text(text 点击的次数${counterState.value},fontSize 20.sp)Button(onClick{//修改状态值counterState.value 1}){Text(点击按钮,fontSize 18.sp)}} }在这种方式中是直接引用以及修改状态counterState的value属性值。当状态值发生变化界面也进行重构。运行效果如下所示 图1运行效果 2.方式二var value by remember { mutableStateOf(default) } 在这种方式中采用了代理的方式来直接获取或设置状态内部包含的value属性值。在这种方式中必须导入 import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue import androidx.compose.runtime.remember 示例代码如下 Preview Composable fun CountScreen(){var counter by remember {mutableStateOf(0)}Column(modifier Modifier.fillMaxSize(),horizontalAlignment Alignment.CenterHorizontally,verticalArrangement Arrangement.Center){Text(text 点击的次数${counter},fontSize 20.sp)Button(onClick{//修改状态值counter 1}){Text(点击按钮,fontSize 18.sp)}} }在上述代码中直接将状态包含的value值进行设置和修改。因此,上述代码的counter就是一个var变量实际上就是对应状态的value属性值。 这时运行效果如图1所示 3.方式三val (value, setValue) remember{ mutableStateOf(default) } 第三种方式表达形式有些奇怪。其中value对应的是状态的value属性的值而设置状态的value属性是通过指定的setValue来实现的。 示例代码如下 Preview Composable fun CountScreen(){val (counter,setValue) remember {mutableStateOf(0)}Column(modifier Modifier.fillMaxSize(),horizontalAlignment Alignment.CenterHorizontally,verticalArrangement Arrangement.Center){Text(text 点击的次数${counter},fontSize 20.sp)Button(onClick{//修改状态值setValue(counter1)}){Text(点击按钮,fontSize 18.sp)}} }这时运行效果如图1所示 二、无状态的可组合函数和有状态的可组合函数 因为可组合函数对参数的处理不同导致了两种形式的可组合函数。 1.无状态的可组合Stateless Composable 无状态的可组合形式就是函数定义形参通过调用时依赖传递的实参实现界面的重构。这种的可组合形式称为无状态的可组合。如下列代码所示 Composable fun CountScreen(counter:Int){Box(contentAlignment Alignment.Center,modifier Modifier.size(300.dp,200.dp)){Text(text 点击的次数${counter},fontSize 20.sp)} }要调用以上的可组合函数必须传递一个整型的数值。 2.有状态的可组合Stateful Composable 有状态的可组合形式就是函数没有定义形参。通过定义内部的状态值如果状态值发生变化会导致界面进行重构。在下列定义的DisplayScreen就是一个有状态的可组合函数。DisplayScreen通过点击按钮使得状态值发生变化导致界面的重构。在该函数中实现对上述无状态可组合函数CountScreen的调用代码如下 Preview Composable fun DisplayScreen(){//定义状态值 var counter by remember{mutableStateOf(0)}Column(modifierModifier.fillMaxSize(), horizontalAlignment Alignment.CenterHorizontally){//调用无状态的可组合函数CountScreenCountScreen(counter)Button(onClick {counter1}){Text(点击按钮)}} }以上两个可组合函数很好的解释了什么是无状态的和有状态的。 三、状态提升 在组合函数中在上述的CounterScreen可组合函数中内部状态值的变化导致可组合进行界面的重组。如果其他可组合项共用界面元素状态并在不同位置将界面逻辑应用到状态则这时需要在界面层次结构中提升状态所在的层次。这样做会使可组合项的可重用性更高并且更易于测试。具体表现形式是将有状态的可组合函数中的状态移至可组合项的调用方使得原来的有状态的可组合函数变成无状态的形式。 场景一有状态的可组合函数没有状态提升 OptIn(ExperimentalMaterial3Api::class) Composable fun DisplayScreen(){val messageState remember{mutableStateOf()}Row(horizontalArrangement Arrangement.Center, modifier Modifier.fillMaxWidth()){TextField(modifier Modifier.wrapContentWidth(),value ${messageState.value},label {Text(消息)},leadingIcon{Icon(Icons.Filled.Info,contentDescription message)},onValueChange{messageState.value it})} } 场景二状态提升 状态提升常规需要对相应的状态需要考虑替换成可组合函数的两个参数 valueT需要修改的状态的值action(T)-Unit :请求修改值的事件 修改上述函数如下所示 OptIn(ExperimentalMaterial3Api::class) Composable fun DisplayScreen(message:String,action:(String)-Unit){Row(horizontalArrangement Arrangement.Center, modifier Modifier.fillMaxWidth()){TextField(modifier Modifier.wrapContentWidth(),value ${message},label {Text(消息)},leadingIcon{Icon(Icons.Filled.Info,contentDescription message)},onValueChange{action.invoke(it)})} }这个DisplayScreen函数修改为一个无状态的函数需要调用该函数形式如下 Preview Composable fun MainScreen(){var input by remember{mutableStateOf(请输入)}Box(modifier Modifier.fillMaxSize(),contentAlignment Alignment.Center){//调用无状态的可组合函数DisplayContentDisplayContent(message input,action {it:String-input it})} }在MainScreen中通过传递实参input和对应action事件给DisplayScreen这样使得原来的DisplayScreen函数的状态提升到MainScreen中。 三、状态丢失 任何Android应用都可能因为活动Activity重新创建或者进程导致丢失界面的状态。 现在修改手机模拟器的设置Settings-Display-Auto-rotate Screen为true如下所示 图2 设置模拟器的为自动旋转 运行上述的DisplayScreen然后旋转手机模拟器运行情况如下图所示 图3 DisplayScreen界面的运行效果 配置的变化导致状态丢失会导致移动应用运行的连续性遭到破坏。 四、保留状态 要解决重新创建活动或进程导致状态的丢失问题则可以通过rememberSaveable来保留状态使得重新创建活动或进程依然可以使用原有的状态。 rememberSaveable 通过保存的实例状态机制将界面元素状态存储在 Bundle 中。 自动将基元类型存储到 Bundle 中。如果是自定义的类实现Parcelable实现序列化可以通过Bundle来传递数据。使用listSaver 和 mapSaver 等 ComposeAPI实现会扩展 Compose 运行时 Saver 类的自定义 Saver类。 方式一自动将基元类型和实现Parcelable接口的类型的数据存储到 Bundle 中 任何基元类型如String、Int、Double、Float、Boolean、Short、Long等以及实现parcelable接口自定义类型的对象可以通过rememberSaveable中的状态会随着onSaveInstanceState以Bundle的键值对的形式进行存储。这里的关键字就是Composable函数在编译期确定的唯一标识。通过这个唯一标识可以将数据按照键值对保存在Bundle并通过这个关键字进行数据恢复。 在下列示例中自定义类因为需要实现Parcelable为了简化代码需要在项目模块的build.gradle.kt中设置使用kotlin-parcelize插件。 plugins { id(kotlin-parcelize) }自定义一个数据类Employee代码如下 Parcelize data class Employee(val name:String,val gender:String,var salary:Double): ParcelableOptIn(ExperimentalMaterial3Api::class) Preview Composable fun EmployeeScreen(){val userState rememberSaveable {mutableStateOf(Employee(张三,男,5000.0))}var salary by rememberSaveable{mutableStateOf(0.0)}Box(contentAlignment Alignment.Center,modifier Modifier.fillMaxSize()){Column{Text(userState.value.toString())TextField(value ${salary},label{Text(修改工资)},leadingIcon {Icon(imageVector Icons.Filled.Info,contentDescription 工资)},onValueChange {salary it.toDouble()})Button(onClick {userState.value.salary salary}){Text(修改工资)}}} }在上述的代码中定义了两处可保存的状态 val userState rememberSaveable { mutableStateOf(Employee(“张三”,“男”,5000.0)) } var salary by rememberSaveable{mutableStateOf(0.0)} 运行结果如下图所示 图4 EmployeeScreen的运行效果 在这个简单应用中,当屏幕没有横纵屏切换修改文本框的值点击按钮第一行的文本并没有发送变化。这是因为Text中显示UserState.value对应的对象并没有变化只是变化了UserState.value对象的属性salary的值而已。因此点击按钮没有发生文本的变换。但是当切换屏幕的横纵方向时因为重新创建屏幕依附的活动导致从Bundle数据中读取已经保存的状态值第一行的文本内容会发生相应的变化。 方式二实现会扩展 Compose 运行时 Saver 类的自定义 Saver类 自定义Saver类自定义保存状态值的逻辑。通过自定义的Saver类定制数据保存的方式和数据恢复的方式。下面定义一个对应上例Employee数据类的EmployeeSaver类定制保存和恢复Employee数据的逻辑代码如下 object EmployeeSaver: SaverEmployee, Bundle {//恢复成Employee对象override fun restore(value: Bundle): Employee? {return value.getString(name)?.let{name:String-value.getString(gender)?.let{gender:String-value.getDouble(salary)?.let{salary:Double-Employee(name,gender,salary)}}}}//保存到Bundle中override fun SaverScope.save(value: Employee): Bundle? {return Bundle().apply{putString(name,value.name)putString(gender,value.gender)putDouble(salary,value.salary)}} }然后修改EmployeeScreen可组合函数将Employee对象的存储和恢复按照EmployeeSaver指定的逻辑进行对应的代码如下 OptIn(ExperimentalMaterial3Api::class) Preview Composable fun EmployeeScreen(){val userState rememberSaveable(stateSaver EmployeeSaver) {mutableStateOf(Employee(张三,男,5000.0))}var salary by rememberSaveable{mutableStateOf(0.0)}Box(contentAlignment Alignment.Center,modifier Modifier.fillMaxSize()){Column{Text(${userState.value})TextField(value ${salary},label{Text(修改工资)},leadingIcon {Icon(imageVector Icons.Filled.Info,contentDescription 工资)},onValueChange {salary it.toDouble()})Button(onClick {userState.value.salary salary}){Text(修改工资)}}} }运行结果如图4一致。 方式三使用listSaver 和 mapSaver 等 ComposeAPI进行数据保存和恢复 通过listSaver和mapSaver等Compose API定制保存和恢复数据的逻辑修改上述的EmployeeScreen函数代码如下 OptIn(ExperimentalMaterial3Api::class) Preview Composable fun EmployeeScreen(){//定义保存和恢复数据的逻辑val employeeSaver run{mapSaver(save {//定义映射的方式指定键值对进行数据保存逻辑mapOf(name to it.name,gender to it.gender,salary to it.salary)},restore{//定义数据根据映射恢复数据的逻辑Employee(it[name] as String,it[gender] as String,it[salary] as Double)})}val userState rememberSaveable(stateSaver employeeSaver) {mutableStateOf(Employee(张三,男,5000.0))}var salary by rememberSaveable{mutableStateOf(0.0)}Box(contentAlignment Alignment.Center,modifier Modifier.fillMaxSize()){Column{Text(${userState.value})TextField(value ${salary},label{Text(修改工资)},leadingIcon {Icon(imageVector Icons.Filled.Info,contentDescription 工资)},onValueChange {salary it.toDouble()})Button(onClick {userState.value.salary salary}){Text(修改工资)}}} }运行结果如图4一致。 参考文献 (1) 状态和JetPack Compose https://developer.android.google.cn/jetpack/compose/state?hlzh-cn
http://www.dnsts.com.cn/news/258853.html

相关文章:

  • 横翻网站模版整站网站模板
  • 建网站大概多少费用培训心得体会感悟
  • 自己做免费的网站中企动力是不是国企
  • 网站建设运营预算h5直播网站
  • 优化建站phpcms做网站建栏目
  • 大型网站模板建设淘宝网站需要多少钱
  • 黄岩做网站的公司可信网站身份认证
  • 部署wordpress站点无锡大型网站设计公司
  • 做网页兼职网站有哪些网站和软件的区别
  • 哈尔版网站建设沧州做企业网站公司
  • 聊城门户网站建设群晖 wordpress 配置文件
  • 网站页面锚点怎么做商城网站设计教程
  • 中国建设银行网站首页joy国内永久免费crm系统app
  • 阿里云做的网站如何发布wordpress无标题
  • 重庆网络营销网站建设销售wordpress 正在连接
  • 阿里云建设网站的步骤南宁网站建设公司怎么赚钱
  • 网站关键字收录快速排名网站系统
  • 湖南湘信建设工程有限公司网站微信营销软件破解版
  • 南通营销网站开发阳春做网站公司
  • 专业设计网站排名wordpress做门户网
  • 电子商务网站建设卷子张掖网站建设推广
  • 公司网站制作模板wordpress点击页面跳转
  • 网站模版 免费下载网站建设费算什么费用
  • 网站dw建设什么是最经典最常用的网站推广方式
  • 百度如何推广网站织梦网站最新漏洞入侵
  • 网站外链 快速建设那个网站上有做婚礼布场样图的
  • 国外网站发展建设免费创办网站
  • 家居网站建设咨询站外推广免费网站
  • 快速网站seo效果做箱包哪个网站好
  • 笑话类网站用什么做wordpress能上传软件吗