编程思想

Jetpack Compose 是一个适用于 Android 的新式声明性界面工具包。Compose 提供声明性 API,让您可在不以命令方式改变前端视图的情况下呈现应用界面,从而使编写和维护应用界面变得更加容易。此术语需要一些解释说明,它的含义对应用设计非常重要。

  1. //动态内容
  2. @Composable
  3. fun Greeting(names: List<String>) {
  4. for (name in names) {
  5. Text("Hello $name")
  6. }
  7. }
  8. //重组
  9. @Composable
  10. fun ClickCounter(clicks: Int, onClick: () -> Unit) {
  11. Button(onClick = onClick) {
  12. Text("I've been clicked $clicks times")
  13. }
  14. }

以下操作全部都是危险的附带效应:

  • 写入共享对象的属性
  • 更新 ViewModel 中的可观察项
  • 更新共享偏好设置

以下示例展示了一个可组合项,它显示一个列表及其项数:

  1. @Composable
  2. fun ListComposable(myList: List<String>) {
  3. Row(horizontalArrangement = Arrangement.SpaceBetween) {
  4. Column {
  5. for (item in myList) {
  6. Text("Item: $item")
  7. }
  8. }
  9. Text("Count: ${myList.size}")
  10. }
  11. }

状态管理

状态的概念是 Compose 的核心。举个简单的例子:用户在屏幕中输入自己的姓名后,系统会显示一条问候语作为响应。以下代码包含问候语的文本和用于输入姓名的文本字段:

import androidx.compose.runtime.*

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

可组合函数可以使用 remember 可组合项记住单个对象。系统会在初始组合期间将由 remember 计算的值存储在组合中,并在重组期间返回存储的值。您可以使用 remember 存储可变对象和不可变对象。

引入状态

状态下降、事件上升的这种模式称为“单向数据流”

image.png


ViewModel 和状态

在 Jetpack Compose 中,您可以使用 ViewModel 公开可观察的存储器(如 LiveDataFlow)中的状态,还可以使用它处理影响相应状态的事件。上面的 HelloScreen 示例使用如下所示的 ViewModel 实现:

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") }
        )
    }
}

observeAsState.observeAsState()) 可观察 LiveData<T> 并返回 State<T> 对象,每当 LiveData 发生变化时,该对象都会更新。State<T> 是 Jetpack Compose 可以直接使用的可观察类型。仅当 LiveData 在组合中时,observeAsState 才会观察 LiveData。


使用 remember

可组合函数可以使用 remember 可组合项记住单个对象。系统会在初始组合期间将由 remember 计算的值存储在组合中,并在重组期间返回存储的值。remember 既可用于存储可变对象,又可用于存储不可变对象。

//remember 存储不可变值
@Composable
fun FancyText(text: String) {
    // by passing text as a parameter to remember, it will re-run the calculation on
    // recomposition if text has changed since the last recomposition
    val formattedText = remember(text) { computeTextFormatting(text) }
    /*...*/
}

//使用 remember 在可组合项中创建内部状态
var expanded by remember { mutableStateOf(false) }

//在可组合项中修改内部状态
IconButton(onClick = { expanded = true }, /* … */) {
   // ...
}

在可组合项中声明 MutableState 对象的方法有三种:

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }<br />


在 Jetpack Compose 中使用其他类型的状态(不看,不学,就是了解下)

  • LiveData
  • Flow.collectAsState(androidx.compose.runtime.kotlinx.coroutines.flow.Flow.collectAsState.R,%20kotlin.coroutines.CoroutineContext))
  • RxJava2