1.【模擬面試追問|平台能力】 舊 App 讀 BLE 廣播式磅秤的方式,是用 Handler 排程:開始掃描、10 秒後停止、再重新開始,掃到的讀值透過 callback 交給畫面。新版打算改成:
interface ScaleDevice {
val readings: Flow<WeightReading>
}
// 實作用 callbackFlow 包 BLE 掃描:開始收集就開始掃,停止收集就停止掃
面試官順著這個設計往下追問:
callbackFlow 裡忘了寫 awaitClose { ... },或寫了但沒有在裡面停止掃描,分別會發生什麼事?readings,會開兩次掃描還是一次?如果你希望只掃一次,要怎麼做?兩者都離開畫面後,掃描應該立刻停,還是等幾秒?為什麼?不看大綱,寫下你會怎麼回答。
我的回答:
2.【預測再驗證|測試與品質】 為了不靠真的磅秤測試 ViewModel,你寫了一個假的裝置,用 callbackFlow 模擬「磅秤在很短時間內送出大量讀值」:
class FakeScaleDevice : ScaleDevice {
override val readings: Flow<WeightReading> = callbackFlow {
repeat(1_000) { i -> trySend(WeightReading(grams = i)) }
awaitClose { }
}
}
@Test
fun `a slow collector`() = runTest {
val received = mutableListOf<Int>()
val job = launch {
FakeScaleDevice().readings.collect {
delay(10) // 模擬畫面處理得比較慢
received += it.grams
}
}
advanceUntilIdle()
job.cancel()
println("收到 ${received.size} 筆,最後一筆是 ${received.lastOrNull()}")
}
收集端收到幾筆?最後一筆是多少?先寫下預測與理由,再跑測試驗證。接著把 callbackFlow { ... } 後面分別加上 .conflate()、.buffer(Channel.UNLIMITED),再各預測一次。
最後判斷:對秤重這件事來說,「中間的讀值掉了」可以接受嗎?你會選哪一種寫法?如果你的測試只送 3 筆讀值,這三種寫法的差別還測得出來嗎?
我的回答:
(待補)