上一篇我们讲了《Channel 与 callbackFlowGoogle 为什么还要设计第三套模型》我们最终得到了一张完整的知识图谱Flow │ ├── StateFlow │ └── State状态 │ ├── SharedFlow │ └── Event事件 │ ├── Channel │ └── Queue队列 │ └── callbackFlow └── Callback → Queue → Flow很多同学看到这里会产生一个疑问callbackFlow 到底有什么用 直接用回调不行吗事实上callbackFlow 解决的是 Android 开发中最常见的问题系统SDK大量使用Callback 而业务代码越来越倾向FlowGoogle 需要一座桥梁。这座桥梁就是callbackFlow一、Android 世界到处都是 Callback例如定位locationManager.requestLocationUpdates( provider, 1000L, 0f, listener )蓝牙bluetoothGattCallback.onConnectionStateChange()WebSocketoverride fun onMessage( webSocket: WebSocket, text: String )CameracameraStateCallback下载downloadListener这些 API 有一个共同特点系统主动通知你这就是Callback模型二、Callback 的痛点传统写法webSocket.setListener(object : MessageListener { override fun onMessage(msg: String) { updateUI(msg) } })刚开始没问题。但随着业务变复杂过滤 防抖 生命周期感知 异常处理 线程切换开始越来越难受。例如收到消息 ↓ 过滤空消息 ↓ 防抖 ↓ 切换主线程 ↓ 更新UI全部手写。代码越来越乱。三、Flow 的优势如果变成 FlowwebSocketFlow() .filter { it.isNotBlank() } .debounce(300) .flowOn(Dispatchers.IO) .collect { updateUI(it) }是不是瞬间舒服了问题来了Callback 怎么变成 Flow答案callbackFlow四、第一个 callbackFlow以定位为例fun locationFlow() callbackFlow { val listener object : LocationListener { override fun onLocationChanged(location: Location) { trySend(location) } } locationManager.requestLocationUpdates( provider, 1000L, 0f, listener ) awaitClose { locationManager.removeUpdates(listener) } }使用locationFlow() .collect { location - Log.d(Location, $location) }这样Callback ↓ Flow完成转换。五、callbackFlow 核心原理很多人第一次看到trySend()会疑惑不是 emit 吗这里要回忆上一篇内容。SharedFlow发送emit() tryEmit()callbackFlow发送send() trySend()为什么因为callbackFlow 底层不是SharedFlow而是Channel六、callbackFlow 内部到底发生了什么本质模型Callback ↓ Channel ↓ Flow ↓ Collector例如override fun onLocationChanged(location) { trySend(location) }其实就是定位回调来了 ↓ 塞进Channel ↓ Collector消费所以callbackFlow Channel Flow包装七、awaitClose 到底是什么很多人只会背awaitClose { ... }但不知道为什么。其实Callback注册了 就必须注销例如locationManager.requestLocationUpdates(...)如果不注销Activity退出 定位还在跑直接内存泄漏所以awaitClose { locationManager.removeUpdates(listener) }相当于onDestroy的作用。八、WebSocket 实战以前socket.setListener { }改造成fun webSocketFlow() callbackFlow { val listener object : SocketListener { override fun onMessage(msg: String) { trySend(msg) } override fun onClosed() { close() } } socket.setListener(listener) awaitClose { socket.removeListener(listener) } }使用webSocketFlow() .collect { updateUI(it) }是不是一下就统一了九、蓝牙实战BLE 通知override fun onCharacteristicChanged( characteristic: BluetoothGattCharacteristic )改fun bleNotifyFlow() callbackFlow { val callback object : BluetoothGattCallback() { override fun onCharacteristicChanged( gatt: BluetoothGatt, characteristic: BluetoothGattCharacteristic ) { trySend(characteristic.value) } } register(callback) awaitClose { unregister(callback) } }然后bleNotifyFlow() .collect { }即可。十、callbackFlow 和 SharedFlow 到底怎么选这个是面试高频题。如果数据来源是ViewModel主动产生例如Toast Navigation ErrorEvent使用SharedFlow如果数据来源是系统回调 SDK回调 第三方库回调例如定位 蓝牙 WebSocket Camera使用callbackFlow一句话自己发的数据 用SharedFlow 别人回调给你的数据 用callbackFlow十一、最终总结我们终于把整个体系串起来了。StateFlow解决当前是什么状态例如Loading UserInfo PageStateSharedFlow解决刚刚发生了什么事件例如Toast Navigation ErrorEventChannel解决消息如何排队消费例如生产者消费者 任务队列callbackFlow解决如何把Callback接入Flow例如定位 蓝牙 WebSocket Camera 下载进度结语到这里Kotlin Flow 最核心的四种模型已经全部串起来了。StateFlow - State SharedFlow - Event Channel - Queue callbackFlow - Callback以前我觉得这些只是几个API现在回头看它们其实对应的是状态 事件 队列 回调四种完全不同的数据流动方式。当真正理解这四个模型以后再看 Kotlin Flow你会发现整个协程体系突然变得异常清晰。