Android Kotlin 最简实现自定义事件通知MainViewModel的方法
最短实现路径
直接替换MutableStateFlow为MutableSharedFlow即可,完全规避你提到的两个问题,不需要额外写枚举、密封类做事件过滤。
StateFlow的定位是状态持有容器,天生要求必须有初始值,且新订阅者订阅时会立即收到当前最新状态,从设计上就不适合做一次性事件通知;而SharedFlow是专门为事件推送场景设计的,无强制初始值,只有主动发送事件时才会触发订阅者的收集逻辑。
标准实现代码
// MainViewModel.kt import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch class MainViewModel : ViewModel() { // 注意:生产环境建议通过构造传入CustomWebViewClient实例,不要在ViewModel内部直接new,便于测试 private val client = CustomWebViewClient() init { viewModelScope.launch { client.onPageFinished.collect { loadedUrl -> // 仅在onPageFinished实际触发时执行,拿到真实加载完成的url // 写你的业务逻辑即可 } } } }
// CustomWebViewClient.kt import android.webkit.WebView import android.webkit.WebViewClient import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow class CustomWebViewClient : WebViewClient() { // 参数配置说明: // replay=0:不给新订阅者重播历史事件,避免订阅时收到旧回调 // extraBufferCapacity=1:缓冲1个事件,避免事件触发时暂无可收集的协程导致事件丢失 private val _onPageFinished = MutableSharedFlow<String>(replay = 0, extraBufferCapacity = 1) val onPageFinished = _onPageFinished.asSharedFlow() override fun onPageFinished(view: WebView?, url: String) { // 直接发送真实url,不需要传无意义的空字符串占位 _onPageFinished.tryEmit(url) } }
如果你根本不需要获取回调里的url参数,直接把MutableSharedFlow的泛型改成Unit即可,发送时调用_onPageFinished.tryEmit(Unit),连参数都不用传。
更极简的轻量实现
如果你不想引入Flow,要最短代码,可以直接用函数类型当回调,没有额外依赖:
class CustomWebViewClient : WebViewClient() { // 给个默认空实现,不用做非空判断 var onPageFinished: (url: String) -> Unit = {} override fun onPageFinished(view: WebView?, url: String) { onPageFinished(url) } } // ViewModel中使用 class MainViewModel : ViewModel() { private val client = CustomWebViewClient().apply { onPageFinished = { loadedUrl -> // 业务逻辑 } } }
这种写法代码量最少,性能开销最低,只需要注意:如果WebView的生命周期长于ViewModel,要在页面销毁时把回调置空,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Viewed
相关产品推荐
相关产品推荐

