kotlin: 用select选择“更快的结果”

一,代码:

例子:需要访问缓存和网络来获取数据,
如果从缓存先返回,先更新ui,从网络获取数据后再更新一次,
如果从网络先返回,更新ui

数据类:

data class Product(
    //id
    val productId: String,
    //价格
    val price: Double,
    // 是不是缓存信息
    val isCache: Boolean = false
)

调用:

        //处理按钮点击事件
        binding.button1.setOnClickListener {
            runBlocking {
                //从cache获取数据
                suspend fun getCacheInfo(productId: String): Product? {
                    delay(300L)
                    return Product(productId, 9.9)
                }
                //从网络获取数据
                suspend fun getNetworkInfo(productId: String): Product? {
                    delay(200L)
                    return Product(productId, 9.8)
                }
                //更新ui
                fun updateUI(product: Product) {
                    println("${product.productId}==${product.price}")
                }

                val startTime = System.currentTimeMillis()
                val productId = "xxxId"

                // 1,缓存和网络,并发执行
                val cacheDeferred = async { getCacheInfo(productId) }
                val latestDeferred = async { getNetworkInfo(productId) }

                // 2,在缓存和网络中间,选择最快的结果
                val product = select<Product?> {
                    cacheDeferred.onAwait {
                        it?.copy(isCache = true)
                    }

                    latestDeferred.onAwait {
                        it?.copy(isCache = false)
                    }
                }

                // 3,更新UI
                if (product != null) {
                    updateUI(product)
                    println("Time cost: ${System.currentTimeMillis() - startTime}")
                }

                // 4,如果当前结果是缓存,那么再取最新的网络服务结果
                if (product != null) {
                    if  (product.isCache) {
                        println("数据来自缓存");
                        val latest = latestDeferred.await()?: return@runBlocking
                        updateUI(latest)
                        println("Time cost: ${System.currentTimeMillis() - startTime}")
                    } else {
                        println("数据不是来自缓存");
                    }
                }


            }
        }

cache的数据有可能出现问题返回变慢,
我们用 async 搭配 select 来使用。
async 可以实现并发,select 则可以选择最快的结果

代码中要注意的地方:
用 select 这个高阶函数包裹了两次查询的服务,同时传入了泛型参数 Product,代表我们要选择的数据类型是 Product。

用了 async 包裹了 getCacheInfo()、getNetworkInfo() 这两个挂起函数,这是为了让这两个查询实现并发执行。

用 onAwait{} 将执行结果传给了 select{},而 select 才能进一步将数据返回给 product 局部变量。
注意,这里我们用的 onAwait{},而不是 await()

二,测试效果:

cache用时100毫秒时

image

cache用时300毫秒时

image

 

posted @ 2025-08-02 15:00  刘宏缔的架构森林  阅读(7)  评论(0)    收藏  举报