Use Kotlin Flow to do HTTP polling (3)

In fact, it is quite simple to do HTTP polling. For example, we now change it to an HTTP polling based on "How to Use Kotlin Flow in Android Development (2)" :


class CommentRepository(private val apiService: GetCommentService) {
    
    

    var isClosed = false
    private val dispatcher = Dispatchers.IO
    suspend fun getCommentWithId(id: Int): Flow<CommentModel> {
    
    
        
        return channelFlow {
    
    
            while (!isClosed) {
    
    

                val data = apiService.getCommentWithId(id)
                send(data)
                delay(5000)
            }
        }.flowOn(dispatcher)


//        flow {
    
    
//            val data = apiService.getCommentWithId(id)
//            emit(data)
//        }.flowOn(Dispatchers.IO)
    }
    
    fun close() {
    
    
        dispatcher.cancel()
    }
}

In this way, a function of requesting HTTP once in 5 seconds is completed. Let me talk about this channelFlow now.

public fun <T> channelFlow(@BuilderInference block: suspend ProducerScope<T>.() -> Unit): Flow<T> =
    ChannelFlowBuilder(block)

It will create a cold flow object ChannelFlowBuilderPlease add a picture description

It is also ultimately a Flow object. The function we pass to us is the block in the above figure, and eventually it will provide a ProducerScope: it will provide
insert image description here
us with a SendChannel object, which we use to send the produced data in our block. In channelFlow, we let codes running in different coroutine contexts generate data, or let them generate data concurrently. In any case, these generated data can be sent using SendChannel, such as (these two examples are from the official) :

fun <T> Flow<T>.merge(other: Flow<T>): Flow<T> = channelFlow {
    
    
    // collect from one coroutine and send it
    launch {
    
    
        collect {
    
     send(it) }
    }
    // collect and send from this coroutine, too, concurrently
    other.collect {
    
     send(it) }
}

fun <T> contextualFlow(): Flow<T> = channelFlow {
    
    
    // send from one coroutine
    launch(Dispatchers.IO) {
    
    
        send(computeIoValue())
    }
    // send from another coroutine, concurrently
    launch(Dispatchers.Default) {
    
    
        send(computeCpuValue())
    }
}

Because channelFlow generates a cold flow, its startup will only start when the collect terminal operator is activated. channelFlow is thread-safe, don't worry about it producing bad results due to concurrency.

Once the code in our block is executed, the Flow object generated by channelFlow will end. Because it is a cold flow, in order to keep it working, I used a while loop above to keep it working.

If you want to end it, you can get its coroutine context to cancel, such as the close method above.

Probably that much first.

Guess you like

Origin blog.csdn.net/weixin_40763897/article/details/128927710
Recommended