最近使用kotlin的flow,重构之前同事写的网络测速功能,发现flow用起来太舒服了,原本好几个类一堆代码,现在50行就实现了核心逻辑。
实现了,输出每秒网速,最多限制10秒,求平均网速的需求。
private var downLoadUrl =
"https://apkdxdl.vivo.com.cn/appstore/developer/soft/20210901/2021090119212663t7e.apk"
@Test
fun main() = runBlocking {
val durationSeconds = 10000L // 最大测速时间
val speedList = arrayListOf<Double>()
var lastDownloadDataSize = 0L
flow {
val connection = URL(downLoadUrl).openConnection()
connection.connectTimeout = 10000
connection.readTimeout = 10000
var downloadedDataSize = 0L
connection.getInputStream().use { input ->
val byteArray = ByteArray(1024 * 1024 * 8)
var read: Int
val withTimeoutOrNull = withTimeoutOrNull(durationSeconds) {
while (input.read(byteArray).also { read = it } != -1) {
downloadedDataSize += read
emit(downloadedDataSize)
}
return@withTimeoutOrNull "ok"
}
if (withTimeoutOrNull == null) {
println("超过10秒,直接结束")
} else {
println("读取完毕")
}
}
}.flowOn(Dispatchers.IO).buffer(capacity = UNLIMITED)
.sample(1000)
.catch { e ->
println("发生异常,测速失败")
e.printStackTrace()
}
.collect {
println("读取中=$it")
val speed = (it - lastDownloadDataSize) / 1024.0 / 1024.0
speedList.add(speed)
val formattedSpeed = String.format("%.1f", speed)
println("当前网速:" + formattedSpeed + "MB/s")
lastDownloadDataSize = it
}
if (speedList.size >= 3) {
speedList.remove(speedList.max())
speedList.remove(speedList.min())
println("平均网速:" + String.format("%.1f", speedList.average()) + "MB/s")
} else {
println("样本太少,测试失败")
}
}