You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为指定Kotlin抽象函数编写Flow风格的扩展函数?

Kotlin扩展函数实现异步回调转Flow

现有Kotlin抽象函数定义如下:

public abstract fun <T : TargetValue> getAverage(
    metric: StatisticsMetric, 
    interval: DateInterval, 
    timeUnit: TimeUnit,
    mode: GroupingMode, 
    result: (AsyncResult<kotlin.collections.Map<Info, T>, Error>) -> kotlin.Unit
): kotlin.Unit

其中TargetValueV2继承自TargetValue,需要编写扩展函数,让该函数支持链式调用.asFlow(),返回Flow类型结果,目标调用方式如下:

val flowResult = sdk.getAverage<TargetValueV2>(
    metric = TIME,
    interval = DateInterval(startDay, currentDate),
    timeUnit = DAY,
    mode = private
).asFlow()

解决方案

1. 封装请求参数的辅助类

首先定义一个辅助类,用来承接getAverage的调用参数,后续扩展函数基于这个类实现Flow转换:

// 替换YourSdkType为定义getAverage的抽象类/接口的实际类型
class GetAverageRequest<T : TargetValue>(
    internal val sdk: YourSdkType,
    internal val metric: StatisticsMetric,
    internal val interval: DateInterval,
    internal val timeUnit: TimeUnit,
    internal val mode: GroupingMode
)

2. 为SDK添加省略回调的扩展函数

编写扩展函数,让getAverage可以不传result参数,转而返回上面定义的辅助类实例:

fun <T : TargetValue> YourSdkType.getAverage(
    metric: StatisticsMetric,
    interval: DateInterval,
    timeUnit: TimeUnit,
    mode: GroupingMode
): GetAverageRequest<T> {
    return GetAverageRequest(
        sdk = this,
        metric = metric,
        interval = interval,
        timeUnit = timeUnit,
        mode = mode
    )
}

3. 实现.asFlow()扩展函数

基于GetAverageRequest编写asFlow扩展,利用callbackFlow将异步回调转换为Flow(需要依赖kotlinx-coroutines-core库):

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow

fun <T : TargetValue> GetAverageRequest<T>.asFlow(): Flow<AsyncResult<Map<Info, T>, Error>> {
    return callbackFlow {
        sdk.getAverage(
            metric = metric,
            interval = interval,
            timeUnit = timeUnit,
            mode = mode,
            result = { asyncResult ->
                trySend(asyncResult)
                close()
            }
        )
        awaitClose()
    }
}

4. 类型推导优化(可选)

如果希望调用时省略显式类型参数,可以使用reified类型参数优化扩展函数:

inline fun <reified T : TargetValue> YourSdkType.getAverage(
    metric: StatisticsMetric,
    interval: DateInterval,
    timeUnit: TimeUnit,
    mode: GroupingMode
): GetAverageRequest<T> {
    return GetAverageRequest(
        sdk = this,
        metric = metric,
        interval = interval,
        timeUnit = timeUnit,
        mode = mode
    )
}

此时调用可以简化为:

val flowResult = sdk.getAverage(
    metric = TIME,
    interval = DateInterval(startDay, currentDate),
    timeUnit = DAY,
    mode = private
).asFlow()

编译器会根据上下文自动推导T为TargetValueV2。

完整调用示例

// 显式指定类型
val flowResult: Flow<AsyncResult<Map<Info, TargetValueV2>, Error>> = sdk.getAverage<TargetValueV2>(
    metric = TIME,
    interval = DateInterval(startDay, currentDate),
    timeUnit = DAY,
    mode = private
).asFlow()

// 自动推导类型(需reified扩展函数支持)
val flowResult = sdk.getAverage(
    metric = TIME,
    interval = DateInterval(startDay, currentDate),
    timeUnit = DAY,
    mode = private
).asFlow()

内容的提问来源于stack exchange,提问作者yozhik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:35:50