簡體   English   中英

PublishSubject 與 Kotlin 協程(流/通道)

[英]PublishSubject with Kotlin coroutines (Flow/Channel)

我正在使用 retrofit 上傳文件。 我想聽聽Kotlin中的retrofit進度,並在ui上用進度條顯示。 當我對此進行研究時,我在此頁面上使用 PublishSubject 在 java 中找到了一個很好的示例。 通過 Retrofit 2 上傳圖片時是否可以顯示進度條? 我想將其改編為我自己的代碼,但我無法決定是否應該在 Kotlin 中使用 Flow 或 Channel 而不是 PublishSubject。

我的請求體 class 與廣播頻道:

class ProgressRequestBody : RequestBody {
    val mFile: File
    val ignoreFirstNumberOfWriteToCalls : Int

    constructor(mFile: File) : super(){
        this.mFile = mFile
        ignoreFirstNumberOfWriteToCalls = 0
    }

    constructor(mFile: File, ignoreFirstNumberOfWriteToCalls : Int) : super(){
        this.mFile = mFile
        this.ignoreFirstNumberOfWriteToCalls = ignoreFirstNumberOfWriteToCalls
    }
    var numWriteToCalls = 0

    val getProgress = BroadcastChannel<Float>(1)


    override fun contentType(): MediaType? {
        return "image/*".toMediaTypeOrNull()
    }

    @Throws(IOException::class)
    override fun contentLength(): Long {
        return mFile.length()
    }

    @Throws(IOException::class)
    override fun writeTo(sink: BufferedSink) {
        numWriteToCalls++

        val fileLength = mFile.length()
        val buffer = ByteArray(DEFAULT_BUFFER_SIZE)
        val `in` = FileInputStream(mFile)
        var uploaded: Long = 0

        try {
            var read: Int
            var lastProgressPercentUpdate = 0.0f
            read = `in`.read(buffer)
            while (read != -1) {

                uploaded += read.toLong()
                sink.write(buffer, 0, read)
                read = `in`.read(buffer)

                // when using HttpLoggingInterceptor it calls writeTo and passes data into a local buffer just for logging purposes.
                // the second call to write to is the progress we actually want to track
                if (numWriteToCalls > ignoreFirstNumberOfWriteToCalls ) {
                    val progress = (uploaded.toFloat() / fileLength.toFloat()) * 100f
                    //prevent publishing too many updates, which slows upload, by checking if the upload has progressed by at least 1 percent
                    if (progress - lastProgressPercentUpdate > 1 || progress == 100f) {
                        // publish progress
                        getProgress.send(progress)
                        lastProgressPercentUpdate = progress
                    }
                }
            }
        } finally {
            `in`.close()
        }
    }


    companion object {

        private val DEFAULT_BUFFER_SIZE = 2048
    }
}

問題是broadcastChannel.send(progress)希望 function 暫停,但 RequestBody writeTo方法不應該暫停。 在這種情況下,我很困惑。 我應該使用 Flow 還是 BroadCastChannel? 你能幫助我嗎?

你應該使用 MutableStateFlow:

val getProgress = MutableStateFlow<Float>(0f) // Initial value is 0

然后:

getProgress.value = progress

查看更多: StateFlow 和 SharedFlow

val getProgress = MutableSharedFlow<Float>(extraBufferCapacity = 1) getProgress.tryEmit(progress)

使用廣播發布進度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM