第十一章:Kotlin 进阶与 Android 原理

本章深入 Kotlin 高级语言特性:协程原理、Flow 冷热流、委托属性实现、DSL 设计、以及 Android Binder 通信机制、Handler/Looper 消息队列、Choreographer 渲染框架等底层原理。


📋 章节目录

主题
11.1 Kotlin 协程原理(CPS / Continuation 状态机)
11.2 Flow 冷热流原理
11.3 委托属性(Delegate Property)
11.4 Kotlin DSL 与内联函数
11.5 Android Binder 通信机制
11.6 Handler / Looper / MessageQueue
11.7 Choreographer 与 VSYNC 渲染
11.8 Jetpack Compose 重组原理

11.1 Kotlin 协程原理

CPS 变换与 Continuation 状态机

Kotlin 编译器将 suspend 函数通过 CPS(Continuation-Passing Style) 变换为状态机:

kotlin 复制代码
// 原始 suspend 函数
suspend fun fetchUserAndOrder(userId: Int): Pair<User, Order> {
    val user = fetchUser(userId)        // 挂起点 1
    val order = fetchOrder(user.orderId) // 挂起点 2
    return user to order
}

// 编译器将其转换为(伪代码):
class FetchUserAndOrderStateMachine(
    private val completion: Continuation<Pair<User, Order>>
) : Continuation<Any?> {

    var state = 0        // 当前执行到哪个挂起点
    var user: User? = null

    override val context = completion.context

    override fun resumeWith(result: Result<Any?>) {
        when (state) {
            0 -> {
                // 第一次调用:执行 fetchUser,挂起
                state = 1
                val future = fetchUser(userId, this) // 传入 this 作为回调
                if (future == COROUTINE_SUSPENDED) return // 真正挂起
                // 如果没有挂起(同步完成),继续往下
                user = future as User
                resumeWith(Result.success(user))
            }
            1 -> {
                // fetchUser 完成后恢复:执行 fetchOrder
                user = result.getOrThrow() as User
                state = 2
                val future = fetchOrder(user!!.orderId, this)
                if (future == COROUTINE_SUSPENDED) return
                resumeWith(result)
            }
            2 -> {
                // fetchOrder 完成后恢复:返回结果
                val order = result.getOrThrow() as Order
                completion.resumeWith(Result.success(user!! to order))
            }
        }
    }
}

CoroutineScope 与结构化并发

kotlin 复制代码
// 结构化并发:子协程的生命周期与父协程绑定
fun structuredConcurrencyDemo() {
    val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)

    scope.launch {
        // 父协程
        val child1 = async { fetchUser(1) }
        val child2 = async { fetchOrder(1) }

        // 一个子协程失败不影响其他(SupervisorJob)
        try {
            val user = child1.await()
            val order = child2.await()
        } catch (e: Exception) {
            // 处理失败
        }

        // scope 取消时,child1 和 child2 都会被取消
    }

    // 取消整个 scope(包含所有子协程)
    scope.cancel()
}

// 协程上下文(CoroutineContext)
fun contextDemo() {
    val context = Dispatchers.IO +              // 线程池
                  CoroutineName("MyCoroutine") + // 命名(调试用)
                  SupervisorJob() +              // Job:控制生命周期
                  CoroutineExceptionHandler { _, e -> // 异常处理
                      Log.e("Coroutine", "Unhandled exception", e)
                  }

    CoroutineScope(context).launch {
        // 在 IO 线程池执行,带有协程名和异常处理
    }
}

// withContext:在不同线程切换
suspend fun multiThreadExample(): String {
    val data = withContext(Dispatchers.IO) {
        // IO 线程:执行网络请求、文件读写
        fetchDataFromNetwork()
    }
    // 回到调用方的 Context(如 Main 线程)
    return processData(data)
}

private suspend fun fetchDataFromNetwork(): String = "data"
private fun processData(data: String): String = data

协程取消机制(Cooperative Cancellation)

kotlin 复制代码
// 协程取消是协作式的(非强制终止)
suspend fun cancellableWork() {
    repeat(1000) { i ->
        // ✅ 定期检查取消状态
        if (!isActive) return  // 提前返回
        // 或者:
        ensureActive()         // 如果已取消,抛出 CancellationException

        // ✅ 挂起点(suspend)会自动检查取消
        delay(100)             // 挂起时如果已取消,自动抛出异常

        doWork(i)
    }
}

// ❌ 无挂起点的密集计算无法自动取消
suspend fun nonCancellableBad() = withContext(Dispatchers.Default) {
    var result = 0L
    for (i in 0..Long.MAX_VALUE) {
        result += i // 没有 isActive 检查,无法取消!
    }
    result
}

// ✅ 密集计算加入取消检查
suspend fun cancellableComputation() = withContext(Dispatchers.Default) {
    var result = 0L
    for (i in 0..1_000_000L) {
        ensureActive() // 每次循环检查取消状态
        result += i
    }
    result
}

// withContext(NonCancellable):不可取消区域(如资源释放)
suspend fun withNonCancellable() {
    try {
        // 可取消的工作
    } finally {
        withContext(NonCancellable) {
            // 即使协程被取消,此处也会执行(用于清理资源)
            closeConnection()
        }
    }
}

private fun closeConnection() {}
private fun doWork(i: Int) {}

11.2 Flow 冷热流原理

冷流(Cold Flow)vs 热流(Hot Flow)

复制代码
冷流(Flow):
  - 创建时不产生数据
  - 每个 collect 触发一个独立的流
  - 典型:flow { } builder、Room DAO 返回的 Flow

热流(SharedFlow / StateFlow):
  - 独立于 collector 产生数据
  - 多个 collector 共享同一流
  - 典型:MutableStateFlow、MutableSharedFlow、广播
kotlin 复制代码
// 冷流原理:每次 collect 执行 producer block
fun coldFlowExample() {
    val coldFlow = flow {
        println("开始生产数据")  // 每次 collect 都会打印
        emit(1)
        emit(2)
        emit(3)
    }

    // 两个 collector,产生两个独立的流
    runBlocking {
        coldFlow.collect { println("Collector1: $it") }
        coldFlow.collect { println("Collector2: $it") }
    }
    // 输出:
    // 开始生产数据
    // Collector1: 1, 2, 3
    // 开始生产数据
    // Collector2: 1, 2, 3
}

// Flow 操作符原理(每个操作符都是一个新的 Flow)
val transformedFlow = flow { emit(1); emit(2); emit(3) }
    .map { it * 2 }           // 返回新 Flow
    .filter { it > 2 }        // 返回新 Flow
    .onEach { /* side effect */ } // 返回新 Flow
    // 最终:链式 Flow,collect 时从上游传递

// StateFlow 实现原理
class CustomStateFlow<T>(initialValue: T) {
    private var _value = initialValue
    private val collectors = mutableListOf<FlowCollector<T>>()

    // 更新时通知所有 collector
    suspend fun setValue(newValue: T) {
        if (_value != newValue) { // 去重:相同值不通知
            _value = newValue
            collectors.forEach { it.emit(newValue) }
        }
    }
}

// SharedFlow vs StateFlow
// StateFlow:永远有值(初始值),Collector 立即收到当前值,去重,replay=1
// SharedFlow:可配置 replay(多久的历史值),不去重,无初始值
val stateFlow = MutableStateFlow(0)          // 有初始值,replay=1,去重
val sharedFlow = MutableSharedFlow<Int>(     // 可配置
    replay = 0,          // 不缓存历史
    extraBufferCapacity = 64,
    onBufferOverflow = BufferOverflow.DROP_OLDEST
)

// 将冷流转为热流(shareIn / stateIn)
class NetworkRepository(
    private val api: Api,
    private val scope: CoroutineScope
) {
    // 将冷流转为热 StateFlow(多个订阅者共享同一网络请求)
    val networkStatus: StateFlow<NetworkStatus> = flow {
        // 定期刷新网络状态
        while (true) {
            emit(api.checkStatus())
            delay(30_000)
        }
    }.stateIn(
        scope = scope,
        started = SharingStarted.WhileSubscribed(5_000), // 无订阅者 5s 后停止
        initialValue = NetworkStatus.Unknown
    )
}

Flow 错误处理与背压

kotlin 复制代码
// catch:捕获上游异常
fun errorHandlingFlow() {
    flow {
        emit(1)
        throw IOException("网络错误")
        emit(2) // 不会执行
    }
    .catch { e ->
        emit(-1) // 发送降级值
        // 或者 throw e 重新抛出
    }
    .onCompletion { cause ->
        // 无论正常/异常结束都会调用
        println("流结束,原因:$cause")
    }
}

// buffer:生产者不等消费者(背压处理)
fun backpressureHandling() {
    flow {
        repeat(100) { i ->
            emit(i) // 快速生产
        }
    }
    .buffer(capacity = 64) // 缓冲区
    .conflate()             // 只保留最新值(丢中间值)
    .collectLatest { value ->
        // 如果新值来了,取消当前处理,处理最新值
        delay(100) // 慢速消费
        processValue(value)
    }
}

private fun processValue(value: Int) {}

11.3 委托属性(Delegate Property)

kotlin 复制代码
// 委托属性原理:operator getValue / setValue
class LazyDelegate<T>(private val initializer: () -> T) {
    private var value: T? = null

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value ?: initializer().also { value = it }
    }
}

// 自定义 by lazy 等效实现
val expensiveValue: String by LazyDelegate { computeExpensiveValue() }

// 标准委托
val lazyValue: String by lazy { "只计算一次" }
var observableValue: String by Delegates.observable("初始值") { prop, old, new ->
    println("${prop.name}: $old → $new")
}
var vetoableValue: Int by Delegates.vetoable(0) { _, _, new ->
    new >= 0 // 只允许非负数
}

// Map 委托(从 Map 读取属性)
class UserConfig(map: Map<String, Any?>) {
    val name: String by map
    val age: Int by map
    val email: String by map
}
val config = UserConfig(mapOf("name" to "张三", "age" to 25, "email" to "zhang@example.com"))
println(config.name) // "张三"

// ViewModel 中的 by viewModels()
class MyFragment : Fragment() {
    private val viewModel: MyViewModel by viewModels() // 委托工厂创建 ViewModel
    private val sharedViewModel: SharedViewModel by activityViewModels()
}

// Compose 中的 by remember / by state
@Composable
fun ComposeDelegatesDemo() {
    var count by remember { mutableStateOf(0) } // 委托 MutableState
    val isEven by remember(count) { derivedStateOf { count % 2 == 0 } }

    Column {
        Text("计数:$count,${if (isEven) "偶数" else "奇数"}")
        Button(onClick = { count++ }) { Text("增加") }
    }
}

private fun computeExpensiveValue(): String = "expensive"

11.4 Kotlin DSL 与内联函数

构建类型安全 DSL

kotlin 复制代码
// HTML DSL 示例
@DslMarker
annotation class HtmlDsl

@HtmlDsl
class TagBuilder(private val tagName: String) {
    private val children = mutableListOf<String>()
    private val attributes = mutableMapOf<String, String>()

    fun attr(name: String, value: String) { attributes[name] = value }

    fun tag(name: String, block: TagBuilder.() -> Unit) {
        val child = TagBuilder(name).also(block).build()
        children.add(child)
    }

    fun text(content: String) { children.add(content) }

    fun build(): String {
        val attrs = attributes.entries.joinToString(" ") { "${it.key}=\"${it.value}\"" }
        val attrsStr = if (attrs.isNotBlank()) " $attrs" else ""
        return "<$tagName$attrsStr>${children.joinToString("")}</$tagName>"
    }
}

fun html(block: TagBuilder.() -> Unit): String = TagBuilder("html").also(block).build()

// 使用
val page = html {
    tag("head") {
        tag("title") { text("Android 文档") }
    }
    tag("body") {
        attr("class", "main")
        tag("h1") { text("Hello Android!") }
    }
}

// Compose-like DSL(构建者模式)
@DslMarker annotation class RequestDsl

@RequestDsl
class NetworkRequest private constructor() {
    var url: String = ""
    var method: String = "GET"
    var timeout: Long = 30_000L
    private val headers = mutableMapOf<String, String>()
    private var body: String? = null

    fun headers(block: MutableMap<String, String>.() -> Unit) = headers.block()
    fun body(content: String) { body = content }

    fun build(): OkHttp3Request = OkHttp3Request(url, method, headers, body, timeout)

    companion object {
        fun create(block: NetworkRequest.() -> Unit): OkHttp3Request {
            return NetworkRequest().also(block).build()
        }
    }
}

// 使用 DSL
val request = NetworkRequest.create {
    url = "https://api.example.com/products"
    method = "POST"
    timeout = 60_000L
    headers {
        put("Authorization", "Bearer token")
        put("Content-Type", "application/json")
    }
    body("""{"page": 1, "limit": 20}""")
}

data class OkHttp3Request(val url: String, val method: String, val headers: Map<String, String>, val body: String?, val timeout: Long)

内联函数(inline)

kotlin 复制代码
// inline 消除 lambda 的对象创建开销
inline fun <T> measureTime(block: () -> T): Pair<T, Long> {
    val start = System.currentTimeMillis()
    val result = block() // 内联展开,不创建 Function 对象
    return result to System.currentTimeMillis() - start
}

// crossinline:lambda 中不能 return(跨边界)
inline fun runWithCallback(crossinline block: () -> Unit) {
    Thread { block() }.start() // block 跨越了 lambda 边界
}

// noinline:特定参数不内联
inline fun processItems(
    items: List<Int>,
    transform: (Int) -> String,          // 内联
    noinline filter: (String) -> Boolean // 不内联(需要作为对象传递)
): List<String> {
    val filtered: List<String> = items.map(transform).filter(filter)
    return filtered
}

// reified:在内联函数中获取类型信息(必须配合 inline)
inline fun <reified T> parseJson(json: String): T {
    return Gson().fromJson(json, T::class.java) // T::class 在内联后可用
}

// 使用
val user: User = parseJson<User>("""{"name": "张三"}""")
val users: List<User> = parseJson<List<User>>("""[{"name": "张三"}]""")

11.5 Android Binder 通信机制

复制代码
Binder 是 Android 的核心 IPC(进程间通信)机制:

用户进程A(Client)     内核(Binder Driver)     用户进程B(Server,如系统服务)
      │                        │                         │
      │ 1. 调用 transact()     │                         │
      ├──────────────────────→ │                         │
      │                        │ 2. 内核复制数据          │
      │                        ├──────────────────────→  │
      │                        │ 3. onTransact() 回调     │
      │                        │                         │ 执行服务逻辑
      │                        │ 4. 返回结果              │
      │ 5. 返回结果             ← ─────────────────────── │
      ←──────────────────────  │                         │

优点:
  ① 只需一次数据拷贝(Binder 将数据映射到接收方地址空间)
     (相比 Socket 需要两次拷贝:发送方→内核,内核→接收方)
  ② 安全:每次 Binder 调用附带调用方 PID/UID,无法伪造
  ③ 面向对象:Binder 对象像远程方法调用
kotlin 复制代码
// 定义 AIDL 接口
// IProductService.aidl
interface IProductService {
    List<Product> getProducts();
    Product getProductById(int id);
    void updateFavorite(int id, boolean isFavorite);
}

// Server 端(Service 中实现)
class ProductRemoteService : Service() {

    private val binder = object : IProductService.Stub() {
        override fun getProducts(): List<Product> {
            // 在服务进程中运行(Binder 线程池)
            return database.productDao().getAllProductsSync()
        }
        override fun getProductById(id: Int): Product {
            return database.productDao().getProductByIdSync(id)!!.toDomain()
        }
        override fun updateFavorite(id: Int, isFavorite: Boolean) {
            database.productDao().updateFavoriteStatusSync(id, isFavorite)
        }
    }

    override fun onBind(intent: Intent): IBinder = binder
}

// Client 端(绑定服务)
class ProductActivity : AppCompatActivity() {
    private var productService: IProductService? = null

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {
            productService = IProductService.Stub.asInterface(service)
            // 可以调用远程方法(注意:不能在主线程调用耗时方法!)
        }
        override fun onServiceDisconnected(name: ComponentName) {
            productService = null
        }
    }

    override fun onStart() {
        super.onStart()
        bindService(
            Intent(this, ProductRemoteService::class.java),
            serviceConnection,
            Context.BIND_AUTO_CREATE
        )
    }

    override fun onStop() {
        super.onStop()
        unbindService(serviceConnection)
    }
}

11.6 Handler / Looper / MessageQueue

kotlin 复制代码
// 核心原理
/*
Looper:
  - 每个线程可以有一个 Looper
  - 维护一个 MessageQueue(优先级队列)
  - 不断从 MessageQueue 中取出 Message 分发给 Handler

Handler:
  - 绑定到创建它的线程的 Looper
  - sendMessage() → 将 Message 放入 MessageQueue
  - handleMessage() → 在其 Looper 所在线程执行

主线程(Main/UI Thread)启动时自动创建 Looper
*/

// 手动创建 Looper 线程
class WorkThread : Thread("worker") {
    private var handler: Handler? = null
    private var looper: Looper? = null

    @Volatile private var running = true

    override fun run() {
        Looper.prepare() // 创建 MessageQueue
        looper = Looper.myLooper()
        synchronized(this) {
            handler = Handler(looper!!) { msg ->
                when (msg.what) {
                    MSG_TASK -> processTask(msg.obj as Runnable)
                }
                true
            }
            notifyAll() // 通知 handler 已创建
        }
        Looper.loop() // 开始轮询(阻塞)
    }

    fun post(task: Runnable) {
        handler?.sendMessage(Message.obtain(handler, MSG_TASK, task))
    }

    fun quit() {
        looper?.quitSafely() // 处理完当前 Message 后退出
    }

    private fun processTask(task: Runnable) { task.run() }

    companion object { const val MSG_TASK = 1 }
}

// Message 对象池(复用,减少内存分配)
val msg = Message.obtain() // 从对象池获取
msg.what = 1
msg.obj = data
handler.sendMessage(msg)
// 分发后自动回收到对象池

// 延迟消息
handler.postDelayed({ updateUI() }, 1000L)
handler.sendMessageDelayed(Message.obtain(handler, MSG_UPDATE), 500L)

// 取消延迟消息
handler.removeCallbacks(updateRunnable)
handler.removeMessages(MSG_UPDATE)

// 查看 MessageQueue 中的 Message
// 只有 Debug 时才用(反射)

11.7 Choreographer 与 VSYNC 渲染

复制代码
VSYNC(垂直同步)信号:显示器每 16.67ms 发出一次信号,驱动一帧的渲染

VSYNC
  │
Choreographer.FrameCallback
  │
  ├── Input(触摸事件处理)
  │
  ├── Animation(属性动画更新)
  │
  └── Traversal(View 树遍历:measure → layout → draw)
        │
        └── 生成 DisplayList(Record Canvas)
              │
              └── → RenderThread → GPU → 屏幕
kotlin 复制代码
// Choreographer 使用
val choreographer = Choreographer.getInstance()

// 注册下一帧回调(单次)
choreographer.postFrameCallback { frameTimeNanos ->
    val frameTimeMs = frameTimeNanos / 1_000_000
    performAnimation(frameTimeMs)
    // 如果需要持续动画,再次注册
    choreographer.postFrameCallback(this)
}

// View 的 invalidate() 机制
/*
view.invalidate() 
  → ViewRootImpl.scheduleTraversals()
  → Choreographer.postCallback(CALLBACK_TRAVERSAL, traversal)
  → 等待下一个 VSYNC 信号
  → 执行 ViewRootImpl.performTraversals()
     → measure() → layout() → draw()
*/

// 监控帧率(FrameMetrics API)
@RequiresApi(Build.VERSION_CODES.O)
fun monitorFrameMetrics(window: Window) {
    window.addOnFrameMetricsAvailableListener({ _, frameMetrics, _ ->
        val totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION) / 1_000_000
        if (totalDuration > 16) {
            Log.w("FrameMetrics", "Frame took ${totalDuration}ms(Jank!)")
        }
    }, Handler(Looper.getMainLooper()))
}

11.8 Jetpack Compose 重组原理

kotlin 复制代码
/*
Compose 快照系统(Snapshot System):

State(MutableState)存储在 Snapshot 中
当 State 被读取时,当前 Scope 被记录为依赖(ReadObserver)
当 State 被修改时,所有依赖的 Scope 被标记为需要重组
Choreographer 下一帧时,执行所有标记的重组
*/

// 理解 @Composable 函数的调用机制
@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) }

    // Compose Runtime 将此函数包装为 Composable Node
    // 分配一个 "Slot Table" 的内存位置存储 count
    // 当 count 变化时,只重组读取了 count 的部分
    
    Column {
        Text("Count: $count")    // 订阅 count,count 变化时此处重组
        Button(onClick = { count++ }) {
            Text("点击")          // 不读 count,不重组
        }
    }
}

// 副作用 API 的实现原理
@Composable
fun SideEffectDemo() {
    // LaunchedEffect:只在 key 变化时重新执行
    // 实现:比较 key 与上一次,如果不同,取消旧协程,启动新协程
    LaunchedEffect(Unit) {
        // 只在首次组合时执行
    }

    // DisposableEffect:在取消组合时执行清理
    // 实现:在 Composition 的生命周期钩子中注册清理函数
    DisposableEffect(Unit) {
        val observer = MyObserver()
        // 注册
        onDispose {
            // 解注册(组件离开时)
        }
    }

    // rememberUpdatedState:捕获最新值而不触发重组
    // 用途:在长时间回调(如定时器)中使用最新的状态
    val count by remember { mutableStateOf(0) }
    val currentCount by rememberUpdatedState(count)
    LaunchedEffect(Unit) {
        delay(5000)
        println(currentCount) // 5秒后使用最新的 count(而非 LaunchedEffect 启动时的值)
    }
}

// 稳定性系统(Stability System)
/*
Compose 编译器分析 @Composable 函数的参数:
- Stable(稳定):参数不变时,跳过重组(Smart Recomposition)
  - 基本类型(Int, String, Boolean...)
  - @Immutable class
  - @Stable 标注的类
  - 所有 fields 为 stable 的 data class

- Unstable(不稳定):参数变化时,总是重组
  - List, Map, Set(接口,不稳定)→ 改用 kotlinx.collections.immutable
  - 含 var fields 的类
*/

// ✅ 使用不可变集合
implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.8")

@Composable
fun StableList(items: ImmutableList<String>) {
    // items 是稳定类型,列表不变时不重组
    LazyColumn {
        items(items) { item -> Text(item) }
    }
}

Demo 代码:chapter11

kotlin 复制代码
// chapter11/PrinciplesDemo.kt
package com.example.androiddemos.chapter11

import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

@Composable
fun Chapter11PrinciplesDemo() {
    var selectedDemo by remember { mutableStateOf(0) }
    val demos = listOf("协程原理", "Flow 冷热流", "委托属性", "重组分析")

    Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
        Text("Kotlin & Android 原理", style = MaterialTheme.typography.headlineSmall)
        Spacer(Modifier.height(8.dp))
        SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
            demos.forEachIndexed { index, label ->
                SegmentedButton(
                    selected = selectedDemo == index,
                    onClick = { selectedDemo = index },
                    shape = SegmentedButtonDefaults.itemShape(index, demos.size)
                ) { Text(label, style = MaterialTheme.typography.labelSmall) }
            }
        }
        Spacer(Modifier.height(16.dp))
        when (selectedDemo) {
            0 -> CoroutinePrinciplesContent()
            1 -> FlowPrinciplesContent()
            2 -> DelegatePrinciplesContent()
            3 -> RecompositionAnalysisContent()
        }
    }
}

@Composable
private fun CoroutinePrinciplesContent() {
    var coroutineResult by remember { mutableStateOf("点击运行协程示例") }
    val scope = rememberCoroutineScope()

    LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        item {
            Card(modifier = Modifier.fillMaxWidth()) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text("协程 CPS 变换原理", style = MaterialTheme.typography.titleSmall)
                    Spacer(Modifier.height(4.dp))
                    Text(
                        "suspend 函数被编译为状态机\n" +
                        "• state=0:执行第一个挂起点前\n" +
                        "• state=1:第一个挂起点后\n" +
                        "• 每次恢复从 resumeWith() 进入",
                        style = MaterialTheme.typography.bodySmall
                    )
                }
            }
        }
        item {
            Card(modifier = Modifier.fillMaxWidth()) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text("结构化并发示例", style = MaterialTheme.typography.titleSmall)
                    Spacer(Modifier.height(8.dp))
                    Text(coroutineResult)
                    Spacer(Modifier.height(8.dp))
                    Button(onClick = {
                        scope.launch {
                            coroutineResult = "执行中..."
                            val a = async { delay(300); "任务A" }
                            val b = async { delay(500); "任务B" }
                            coroutineResult = "${a.await()} + ${b.await()} 完成(并行执行)"
                        }
                    }) { Text("并行执行 async") }
                }
            }
        }
    }
}

@Composable
private fun FlowPrinciplesContent() {
    var flowLog by remember { mutableStateOf("点击观察 Flow 行为") }
    val scope = rememberCoroutineScope()
    val hotFlow = remember { MutableSharedFlow<Int>(replay = 0) }

    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        Card(modifier = Modifier.fillMaxWidth()) {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("Flow 冷流 vs 热流", style = MaterialTheme.typography.titleSmall)
                Text("• 冷流:每次 collect 触发独立流\n• 热流:多个 collector 共享数据", style = MaterialTheme.typography.bodySmall)
                Spacer(Modifier.height(8.dp))
                Text(flowLog, style = MaterialTheme.typography.bodySmall)
                Spacer(Modifier.height(8.dp))
                Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                    Button(onClick = {
                        scope.launch {
                            flowLog = ""
                            flow { emit(1); emit(2); emit(3) }.collect {
                                flowLog += "冷流: $it\n"
                            }
                        }
                    }) { Text("冷流") }
                    Button(onClick = {
                        scope.launch { hotFlow.emit((1..100).random()) }
                    }) { Text("发射热流值") }
                }
            }
        }
    }
}

@Composable
private fun DelegatePrinciplesContent() {
    // 演示 by remember / by state 委托
    var delegatedCount by remember { mutableStateOf(0) }
    val isPositive by remember(delegatedCount) { derivedStateOf { delegatedCount >= 0 } }

    Card(modifier = Modifier.fillMaxWidth()) {
        Column(modifier = Modifier.padding(16.dp)) {
            Text("委托属性 Demo", style = MaterialTheme.typography.titleSmall)
            Spacer(Modifier.height(8.dp))
            Text("当前值: $delegatedCount(${if (isPositive) "正数" else "负数"})")
            Text("by remember { mutableStateOf(0) } - 读/写委托给 MutableState", style = MaterialTheme.typography.bodySmall)
            Spacer(Modifier.height(8.dp))
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                Button(onClick = { delegatedCount-- }) { Text("-1") }
                Button(onClick = { delegatedCount++ }) { Text("+1") }
                OutlinedButton(onClick = { delegatedCount = 0 }) { Text("归零") }
            }
        }
    }
}

@Composable
private fun RecompositionAnalysisContent() {
    var triggerCount by remember { mutableStateOf(0) }
    var rootRecomposeCount by remember { mutableIntStateOf(0) }
    var childRecomposeCount by remember { mutableIntStateOf(0) }

    // 记录根节点重组次数
    SideEffect { rootRecomposeCount++ }

    Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
        Card(modifier = Modifier.fillMaxWidth()) {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("重组分析", style = MaterialTheme.typography.titleSmall)
                Text("根节点重组次数: $rootRecomposeCount", style = MaterialTheme.typography.bodyMedium)
                Spacer(Modifier.height(8.dp))
                // 子组件 - 读取 triggerCount
                StableChildComponent(
                    count = triggerCount,
                    onRecompose = { childRecomposeCount++ }
                )
                Text("子节点重组次数: $childRecomposeCount", style = MaterialTheme.typography.bodySmall)
                Spacer(Modifier.height(8.dp))
                Button(onClick = { triggerCount++ }) {
                    Text("触发状态变化(第 $triggerCount 次)")
                }
            }
        }
    }
}

@Composable
private fun StableChildComponent(count: Int, onRecompose: () -> Unit) {
    SideEffect { onRecompose() } // 每次重组调用
    Text("子组件读取: $count", style = MaterialTheme.typography.bodySmall)
}

章节总结

知识点 必掌握程度 面试频率
协程 CPS 变换 / 状态机 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
协程取消协作机制 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
结构化并发 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Cold Flow vs Hot Flow ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
StateFlow vs SharedFlow ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
stateIn / shareIn ⭐⭐⭐⭐ ⭐⭐⭐⭐
委托属性原理 ⭐⭐⭐⭐ ⭐⭐⭐⭐
Kotlin inline / reified ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Binder 一次拷贝原理 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Handler / Looper / MessageQueue ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Choreographer / VSYNC ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Compose Snapshot 系统 ⭐⭐⭐⭐ ⭐⭐⭐⭐
相关推荐
studyForMokey1 小时前
【Android面试】设计模式专题
android·设计模式·面试
三少爷的鞋2 小时前
别再写 BaseXXX 了:BaseActivity 和 BaseViewModel 正在毁掉你的架构
android
Trustport2 小时前
ArcGIS Maps SDK For Kotlin 加载Layout中的MapView出错
android·开发语言·arcgis·kotlin
EQ-雪梨蛋花汤2 小时前
【笔记】安卓毛玻璃效果(Blur)实现笔记(使用BlurView)(结尾附:源码)
android·笔记
StackNoOverflow4 小时前
MySQL Explain 返回列详解:从入门到实战,附 SQL 与避坑大全
android
CYRUS_STUDIO12 小时前
Frida 检测与对抗实战:进程、maps、线程、符号全特征清除
android·逆向
csj5013 小时前
安卓基础之《(28)—Service组件》
android
lhbian15 小时前
PHP、C++和C语言对比:哪个更适合你?
android·数据库·spring boot·mysql·kafka
catoop16 小时前
Android 最佳实践、分层架构与全流程解析(2025)
android