Ali Albaali
01/11/2021, 10:53 AMsuspend fun flowProgress(block: (Flow<Int>) -> Unit) {
block(
flow {
do {
val progress: Int // .... getting progress
emit(progress)
} while (true)
}
)
}
The other uses plain callback function:
suspend fun intProgress(block: (Int) -> Unit) {
do {
val progress: Int // .... getting progress
block(progress)
} while (true)
}
Can somebody tell me what's the difference between these two and why should I go with one over the other?gildor
01/11/2021, 10:54 AMgildor
01/11/2021, 10:54 AMgildor
01/11/2021, 10:55 AMAli Albaali
01/11/2021, 10:57 AMAli Albaali
01/11/2021, 10:59 AMgildor
01/11/2021, 11:02 AMThey both gets called in a suspending functionNope, because
block: (Flow<Int>)
is non-suspend lambda, so you cannot do this:
flowProgress { it.collect { publishProgress() } }
gildor
01/11/2021, 11:03 AMAli Albaali
01/11/2021, 11:04 AMfun flowProgress(block: suspend (Flow<Int>) -> Unit)
what if it's like that?gildor
01/11/2021, 11:04 AMgildor
01/11/2021, 11:04 AMgildor
01/11/2021, 11:05 AMAli Albaali
01/11/2021, 11:06 AMgildor
01/11/2021, 11:06 AMAli Albaali
01/11/2021, 11:07 AMgildor
01/11/2021, 11:07 AMgildor
01/11/2021, 11:08 AMgildor
01/11/2021, 11:08 AMgildor
01/11/2021, 11:08 AMfun flowProgress(): Flow<Int> {
return flow {
do {
val progress: Int // .... getting progress
emit(progress)
} while (true)
}
}
gildor
01/11/2021, 11:09 AMAli Albaali
01/11/2021, 11:11 AMinterface Request{
suspend fun progress(flow: Flow<Int>)
suspend fun intProgress(value: Int)
}
gildor
01/11/2021, 11:11 AMupdateAllData()
so usage will be:
updateAllData()
but if it returns Flow, it will do nothing, user should do:
updateAllData().collect()
gildor
01/11/2021, 11:12 AMWhat if it’s implemented in an interface like this or it doesn’t matterWhat is the point of this interface?
gildor
01/11/2021, 11:12 AMAli Albaali
01/11/2021, 11:13 AMoverride suspend fun fetch(data: Url, config: HttpRequestConfig): Result<ByteReadChannel> = runCatching {
with(config) {
client.get(data) {
val statement = HttpStatement(this, client)
statement.execute { response ->
val channel = response.receive<ByteReadChannel>()
val contentLength = response.contentLength()
requireNotNull(contentLength) { "Content-Length header needs to be set by the server." }
progress(
flow {
var total = 0
var readBytes: Int
val buffer = ByteArray(contentLength.toInt())
do {
readBytes = channel.readAvailable(buffer, total, 4096)
total += readBytes
emit(total)
// intProgress(total)
} while (readBytes > 0)
}
)
}
builder()
}
}
}
interface HttpRequestConfig : Fetcher.Config {
fun HttpRequestBuilder.builder()
suspend fun progress(flow: Flow<Int>)
suspend fun intProgress(value: Int)
}
gildor
01/11/2021, 11:13 AMgildor
01/11/2021, 11:13 AMAli Albaali
01/11/2021, 11:14 AMgildor
01/11/2021, 11:14 AMAli Albaali
01/11/2021, 11:14 AMgildor
01/11/2021, 11:15 AMAli Albaali
01/11/2021, 11:15 AMgildor
01/11/2021, 11:15 AMgildor
01/11/2021, 11:15 AMIt’s perform network requestsIt’s not necessary true, it depends on HTTP client implementation
gildor
01/11/2021, 11:16 AMAli Albaali
01/11/2021, 11:16 AMAli Albaali
01/11/2021, 11:17 AMgildor
01/11/2021, 11:17 AMAli Albaali
01/11/2021, 11:17 AMgildor
01/11/2021, 11:17 AMAli Albaali
01/11/2021, 11:18 AMgildor
01/11/2021, 11:18 AMgildor
01/11/2021, 11:20 AMgildor
01/11/2021, 11:20 AMAli Albaali
01/11/2021, 11:21 AMgildor
01/11/2021, 11:56 AMgildor
01/11/2021, 11:56 AMAli Albaali
01/11/2021, 11:57 AMAli Albaali
01/11/2021, 11:57 AMgildor
01/11/2021, 11:58 AMgildor
01/11/2021, 11:58 AMAli Albaali
01/11/2021, 11:59 AMHttpRequestConfig
gildor
01/11/2021, 11:59 AMgildor
01/11/2021, 11:59 AMAli Albaali
01/11/2021, 12:00 PMinterface HttpRequestConfig {
fun HttpRequestBuilder.builder()
suspend fun progress(flow: Flow<Int>)
}
gildor
01/11/2021, 12:01 PMAli Albaali
01/11/2021, 12:01 PMgildor
01/11/2021, 12:01 PMAli Albaali
01/11/2021, 12:02 PMAli Albaali
01/11/2021, 12:02 PMgildor
01/11/2021, 12:03 PMAli Albaali
01/11/2021, 4:35 PMpublic fun fetch(data: Url): Flow<Resource<ByteReadChannel>> = flow {
try {
val requestBuilder = HttpRequestBuilder().apply {
url(data)
}
HttpStatement(requestBuilder, client).execute { response ->
val channel = response.receive<ByteReadChannel>()
val contentLength = response.contentLength()?.toInt()
requireNotNull(contentLength) { "Content-Length header needs to be set by the server." }
var totalBytes = 0
var readBytes: Int
val buffer = ByteArray(contentLength)
do {
readBytes = channel.readAvailable(buffer, totalBytes, 4096)
totalBytes += readBytes
emit(Resource.Loading(totalBytes.toFloat().calculatePercentage(contentLength)))
} while (readBytes > 0)
emit(Resource.Success(channel))
}
} catch (exception: Throwable) {
emit(Resource.Failure(exception))
}
}
This is what you were saying correct?
You're right the code earlier looked weird. The thing is at the beginning it didn't support Loading progress, so I only implemented it with Result. However when adding the progress the whole implementation changes as you said.