📘 Compose 基础概念

声明式UI · 状态管理
⚡ 1. 声明式UI vs 命令式UI

命令式UI (Imperative) 像一份详细的烹饪步骤:你告诉系统“先创建TextView,然后设置文字,再添加到布局……”。而 声明式UI (Declarative) 像一张菜单:“我要一碗牛肉面”,系统负责实现细节。

对比维度命令式 (View系统)声明式 (Jetpack Compose)
编程范式如何做 (How) — 逐步操作UI实例做什么 (What) — 描述UI状态
状态更新手动 findViewById + setText / 通知适配器状态变化 → 自动重组 (Recomposition)
代码可读性分散在 Activity / Fragment / Adapter集中、组合、可预测
学习曲线传统,但回调嵌套复杂初看陌生,但逻辑连贯
典型代码
textView.text = "Hello"
button.setOnClickListener { 
    textView.text = "Clicked" 
}
var text by remember { mutableStateOf("Hello") }
Button(onClick = { text = "Clicked" }) {
    Text(text)
}
🧠 2. Compose 核心思想
Compose 哲学 · 一句话

✦ “UI 是状态的快照” — 当状态改变,Compose 自动重新绘制快照,你只需描述每个状态下的界面。

🔗 3. Compose 与 View 互操作性

Jetpack Compose 完全兼容传统 View 体系,可以在同一个界面中混合使用。三种核心互操作模式:

  1. Compose 中嵌入 View — 使用 AndroidView 包装任何传统 View (如 MapView, WebView)。
  2. View 中嵌入 Compose — 在 XML 布局中添加 ComposeView,调用 setContent。
  3. Fragment / Activity 混合 — 部分页面用 Compose,部分保留 View,共享 ViewModel。
Compose UI @Composable AndroidView (WebView / Map...) 互操作桥梁 ComposeView XML + setContent 传统 View Fragment / XML ComposeView (嵌入Compose) ↔ 双向互操作 · 共享ViewModel / 状态
互操作代码片段
// 在 Compose 中使用传统 View (AndroidView)
@Composable
fun MapComposable() {
    AndroidView(
        factory = { ctx -> 
            MapView(ctx).apply { 
                onCreate(Bundle()) 
                getMapAsync { /* 回调 */ }
            }
        },
        update = { mapView -> mapView.onResume() }
    )
}

// 在 XML 布局中嵌入 Compose (ComposeView)
<androidx.compose.ui.platform.ComposeView
    android:id="@+id/compose_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

// Activity 中绑定
findViewById<ComposeView>(R.id.compose_view).setContent {
    MaterialTheme { 
        Greeting("Android + Compose") 
    }
}
📦 附:ViewModel + Compose 状态管理

在 Compose 中,viewModel() 函数让 ViewModel 与 Composable 生命周期绑定。状态通过 StateFlow 或 mutableStateOf 驱动UI。

// ViewModel 示例
class MyViewModel : ViewModel() {
    private val _count = MutableStateFlow(0)
    val count: StateFlow<Int> = _count.asStateFlow()

    fun increment() { _count.value++ }
}

@Composable
fun CounterScreen(viewModel: MyViewModel = viewModel()) {
    val count by viewModel.count.collectAsState()
    Button(onClick = { viewModel.increment() }) {
        Text("点击次数: $count")
    }
}