Kotlin Flow的6个必知高阶技巧

原文:xuanhu.info/projects/it...

Kotlin Flow的6个必知高阶技巧

一、智能缓冲策略优化流处理

背压问题核心解析

当生产者和消费者速率不匹配时,传统流处理会导致数据积压。Kotlin的buffer()操作符通过创建缓冲区解决该问题:

kotlin 复制代码
flow {
    (1..5).forEach { 
        delay(100)  // 模拟生产延迟
        emit(it)
    }
}.buffer(32)        // 设置32个元素的缓冲区
.collect { value ->
    delay(300)      // 模拟消费延迟
    println(value)
}

技术要点:

  • buffer() 默认使用64个元素的缓冲区
  • 缓冲区满时生产者挂起,避免内存溢出
  • 结合conflate()可丢弃中间值保留最新数据

缓冲策略选择矩阵

二、精准流量控制技巧

节流操作实战

kotlin 复制代码
flow {
    var value = 0
    while (true) {
        emit(value++)
        delay(10)  // 每10ms发射数据
    }
}.conflate()       // 仅保留最新值
.collect {
    delay(100)     // 每100ms处理数据
    println(it)
}

执行效果:

erlang 复制代码
0
12
24
36
...

说明:中间11个值被丢弃,仅处理最新数据

时间窗口采样

kotlin 复制代码
flow {
    (1..20).forEach {
        emit(it)
        delay(50)
    }
}.sample(200)  // 200ms时间窗口采样
.collect {
    println(it) // 输出:4,8,12,16,20
}

三、多流操作高级策略

复合流合并技术

kotlin 复制代码
val flowA = flowOf("A1", "A2", "A3").onEach { delay(100) }
val flowB = flowOf("B1", "B2").onEach { delay(150) }

merge(flowA, flowB).collect {
    println(it) // 输出:A1, B1, A2, A3, B2
}

动态流切换方案

kotlin 复制代码
fun getFlowByType(type: String): Flow<String> = 
    when(type) {
        "A" -> flowOf("A1", "A2")
        "B" -> flowOf("B1", "B2")
        else -> emptyFlow()
    }

flatMapConcat { type ->
    getFlowByType(type) // 顺序执行流
}

四、流共享与状态管理

SharedFlow热流配置

kotlin 复制代码
val sharedFlow = MutableSharedFlow<Int>(
    replay = 2,          // 新订阅者接收最近2个值
    extraBufferCapacity = 10 // 额外缓冲区
)

// 生产者
launch {
    (1..15).forEach {
        sharedFlow.emit(it)
        delay(50)
    }
}

// 消费者1
launch {
    sharedFlow.collect {
        println("C1: $it")
    }
}

// 延迟消费者
launch {
    delay(300)
    sharedFlow.collect {
        println("C2: $it") // 收到13,14(replay=2)
    }
}

StateFlow状态管理

kotlin 复制代码
val state = MutableStateFlow(0)

// 状态更新
fun increment() {
    state.value += 1
}

// 状态监听
state.collect {
    println("状态更新:$it")
}

五、复杂流异常处理

精细化异常捕获

kotlin 复制代码
flow {
    emit(1)
    throw RuntimeException("测试异常")
}.catch { cause ->
    if (cause is IOException) {
        emit(-1)  // 特定异常恢复
    } else {
        throw cause // 重新抛出
    }
}.onCompletion { cause ->
    cause?.let { 
        println("流终止原因: ${it.message}")
    }
}.collect { ... }

超时控制机制

kotlin 复制代码
withTimeoutOrNull(250) {
    flow {
        emit(1)
        delay(300)  // 超时操作
        emit(2)
    }.collect()
} ?: println("操作超时")

六、Flow与响应式UI集成

Android UI状态管理

kotlin 复制代码
class ViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(Loading)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _uiState.value = Loading
            try {
                val data = repository.fetchData()
                _uiState.value = Success(data)
            } catch (e: Exception) {
                _uiState.value = Error(e.message)
            }
        }
    }
}

// Activity中监听
lifecycleScope.launchWhenStarted {
    viewModel.uiState.collect { state ->
        when(state) {
            is Loading -> showProgress()
            is Success -> showData(state.data)
            is Error -> showError(state.message)
        }
    }
}

防抖搜索实现

kotlin 复制代码
searchInputFlow
    .debounce(300)       // 300ms防抖
    .distinctUntilChanged() // 值去重
    .flatMapLatest { query ->
        searchApi(query)   // 取消前次搜索
    }
    .flowOn(Dispatchers.IO) // 切换IO线程
    .collect { results ->
        updateUI(results)
    }

总结

  1. 流量控制三剑客buffer/conflate/sample 应对不同背压场景

  2. 多流操作选择

    • flatMapConcat:顺序执行
    • flatMapMerge:并发执行
    • flatMapLatest:取最新流
  3. 状态共享方案

    • SharedFlow:多订阅者广播
    • StateFlow:单一值状态管理
  4. 生产环境实践

    kotlin 复制代码
    val scope = CoroutineScope(SupervisorJob() + CoroutineExceptionHandler { _, e -> 
         logError(e) 
    })

性能优化

扩展建议:

  1. 结合Channel实现复杂生产者-消费者模型
  2. 使用flowOn精确控制执行上下文
  3. 在Compose中使用collectAsStateWithLifecycle

原文:xuanhu.info/projects/it...

相关推荐
2501_940094027 小时前
mig烧录卡资源 Mig-Switch游戏合集 烧录卡 1.75T
android·游戏·安卓·switch
渡我白衣7 小时前
深入理解 OverlayFS:用分层的方式重新组织 Linux 文件系统
android·java·linux·运维·服务器·开发语言·人工智能
2501_915106328 小时前
iOS性能调优的系统化实践,从架构分层到多工具协同的全流程优化指南(开发者深度版)
android·ios·小程序·架构·uni-app·iphone·webview
stevenzqzq8 小时前
android recyclerview缓存_缓存问题解决办法
android·java·缓存
下位子9 小时前
『OpenGL学习滤镜相机』- Day10: 相机预览与 OpenGL 结合
android·opengl
那就逆流而上吧9 小时前
Android AIDL 的详细讲解和实践指南
android
xiaoxue..10 小时前
深入理解 JavaScript 异步编程:从单线程到 Promise 的完整指南
前端·javascript·面试·node.js
TDengine (老段)11 小时前
TDengine 字符串函数 POSITION 用户手册
android·java·大数据·数据库·物联网·时序数据库·tdengine
2501_9371549312 小时前
神马影视 8.8 源码 2025 版,HDR + 杜比音效 + 零卡顿
android·源码·源代码管理·机顶盒
asjhan12 小时前
Android framework强制修改系统属性
android