欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android的Compose概览

程序员文章站 2022-05-04 07:51:22
...

Compose概览

官方文档
我个人看了下官方的文档,尝试了一下demo,大概做一个个人的理解和记录,还没有深入研究尝试

compose是什么

Android推出的新的,以声明式语言方式,用来进行UI编写的UI库

声明式

常见的是与命令式比较出现,我们以前的常用的是就是命令式语言编写的UI
看了一些介绍的文章,简单的一点理解就是:

命令式编程就像王刚教你做菜,会告诉你每一步做什么
声明式就是直接告诉王刚要吃什么菜,做菜的人是王刚

关于Compose的声明式UI,暂时能感受到的:

  1. 不用写xml文件了
  2. 直接调用compose的库就可以在界面渲染出组件
  3. 猜想这种编写方式以后会方便复用(比如我复用一个compose函数,比复用一个xml+java要简单吧)

声明式更新

扔物线视频
扔物线视频中提到,声明式的重点在于可以自动更新页面,而dataBinding更新的是页面的数据,使用compose的声明式可以更新页面的数据和其他属性,甚至是结构

组合函数

@compose注解的函数,注释告诉编译器,此函数旨在将数据转换为界面,用组合函数作为参数的时候,也要声明有@compose注解

组合函数可以调用其他的组合函数,不会返回任何内容

状态state

简单来说,就是会影响界面发生变化的变量
状态的变化会引起其所在compose函数重构

var value by remember { mutableStateOf(default) }

官方例子中的写法,还提到有其他写法:

val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }

mutableStateOf

创建一个可观察的状态变量,持有单一值。当这个变量变化的时候,会引起函数重组,相关部分界面重新渲染

remember

缓存了状态变量的值

rememberSaveable

这个是相对于remember的,当横竖屏切换的时候,使用remember是不能保存状态值的,使用rememberSaveable就可以

状态提升

这个没有理解清除,但是看代码的意思,是把状态部分抽出去进行了封装

未进行状态提升的时候

@Composable
fun HelloContent() {
   Column(modifier = Modifier.padding(16.dp)) {
       var name by remember { mutableStateOf("") }
       if (name.isNotEmpty()) {
           Text(
               text = "Hello, $name!",
               modifier = Modifier.padding(bottom = 8.dp),
               style = MaterialTheme.typography.h5
           )
       }
       OutlinedTextField(
           value = name,
           onValueChange = { name = it },
           label = { Text("Name") }
       )
   }
}

官方的例子:进行状态提升后

@Composable
fun HelloScreen() {
	var name by rememberSaveable { mutableStateOf("") }

	HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}

如果按照之前的写法,那么name应该是在helloContent中的,我们直接调用helloContent,提升后,我们要调用helloScreen,这样做的好处,官方的总结:

以这种方式提升的状态具有一些重要的属性:

单一可信来源:我们会通过移动状态而不是复制状态,来确保只有一个可信来源。这有助于避免 bug。
封装:只有有状态可组合项能够修改其状态。这完全是内部的。
可共享:可与多个可组合项共享提升的状态。如果想在另一个可组合项中执行 name 操作,可以通过变量提升来做到这一点。
可拦截:无状态可组合项的调用方可以在更改状态之前决定忽略或修改事件。
解耦:无状态 ExpandingCard 的状态可以存储在任何位置。例如,现在可以将 name 移入 ViewModel。

个人理解,也就是这个状态可能影响多个部分,我们把状态封装后,统一状态,统一处理

接入ViewModel和LiveData使用

class HelloViewModel : ViewModel() {

    // LiveData holds state which is observed by the UI
    // (state flows down from ViewModel)
    private val _name = MutableLiveData("")
    val name: LiveData<String> = _name

    // onNameChange is an event we're defining that the UI can invoke
    // (events flow up from UI)
    fun onNameChange(newName: String) {
        _name.value = newName
    }
}


@Composable
fun HelloScreen(helloViewModel: HelloViewModel = viewModel()) {
    // by default, viewModel() follows the Lifecycle as the Activity or Fragment
    // that calls HelloScreen(). This lifecycle can be modified by callers of HelloScreen.

    // name is the current value of [helloViewModel.name]
    // with an initial value of ""
    val name: String by helloViewModel.name.observeAsState("")
    HelloContent(name = name, onNameChange = { helloViewModel.onNameChange(it) })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.h5
        )
        OutlinedTextField(
            value = name,
            onValueChange = onNameChange,
            label = { Text("Name") }
        )
    }
}

很明显的,是替换掉了
remember { mutableStateOf(default) } 这种方式,以
ViewModel.name.observeAsState("") 方式实现

Modifier

官方文档和例子
修饰符,可以用来设置渲染的布局,尺寸等,修饰符声明的顺序很重要,因为是按顺序渲染的