kotlin 创建flow的7种方式

842 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

前言

对于kotlin的flow看过我前面的一些文章应该对其有一定的了解,今天我们一起来看看flow创建的七种方式。

常用方法

flowOf()

flowOf()从给定的一组项目创建一个流实例。基本上,它是一个静态流构建器,其中包含要发出的预定义项。

val demoFlow = flowOf("第一个数据", "第二个数据", "第三个数据")
demoFlow.collect {
      println("$it") 
}

asFlow()

asFlow()是一个扩展函数。您可以将对应的非流数据通过asFlow()转换为 Flow。

// 作为集合转换
val demoList = listOf("第一个数据", "第二个数据", "第三个数据")
val demoFlow = demoList.asFlow()
demoFlow.collect {
      println("$it") 
}

flow{}

从给定的可暂停块创建冷流实例,我们可以在其中手动发出值。当我们开始收集它时,它只会发出一次。

fun demo() = flow {
	emit("需要发射的数据")
	delay(1000) // 发射每隔一秒
}.collect{
	println("$it") 
}

热流

MutableStateFlow

可变状态持有者流向其收集器发出当前值和初始值。MutableStateFlow 是一个热流。有了StateFlow数据就是一种状态。

class DemoViewModel:ViewModel(){
    // 使用热流 MutableStateFlow 
    private val _uiState = MutableStateFlow<UiState>(UiState.Success(""))
    val uiState : StateFlow<UiState> = _uiState
    private val demoList = listOf("第一个数据", "第二个数据", "第三个数据")
    
    fun demoFuction() {
        viewModelScope.launch {
            _uiState.tryEmit(UiState.Loading)
            demoList.asFlow().collect { str ->
                    _uiState.tryEmit(UiState.Success(str))
            }
        }
    }
    // 定义UI状态行为
    sealed class UiState{
       object Loading : UiState()
       data class Success(str:String) : UiState()
    }   
}

MutableSharedFlow

可变共享流,在其所有收集器之间共享所有发出的值。

class DemoViewModel : ViewModel() {
  val sharedFlow = MutableSharedFlow<Int>(
        replay= 1, // 当有新得流需要收集时,它可以接受几个历史数据
        extraBufferCapacity = 3, // 除去replay,MutableSharedFlow还缓存多少数据
        onBufferOverflow = BufferOverflow.DROP_OLDEST // 有三种缓存策略 1. 丢掉最新值 2. 丢掉最旧值 3.等待
    )
    
    // 发射数据
    sharedFlow.tryEmit(1)
    sharedFlow.tryEmit(2)
    sharedFlow.tryEmit(3)

    // 新的收集
    val job1  = sharedFlow.onEach {
        Log.e("Job1","Collected $it")
    }.launchIn(this)
  	// 新的收集
    val job2  = sharedFlow.onEach {
        Log.e("Job2","Collected $it")
    }.launchIn(this)

    delay(1000)
    job1.cancel()
    delay(1000)
    job2.cancel()
    
    // 结果
    // job1打印 Collected2
    // job2打印 Collected2
}

其他方式

ChannelFlow

ChannelFlow 在单独的协程中生成值,而无需等待接收者完成对发射项目的处理。而正常流程按顺序工作,emit()暂停直到消费者完成最新项目的工作。

val demoScope = CoroutineScope(Dispatchers.IO)

val demoFlow = channelFlow {
    println("发送 : 1")
    send("1")
    println("发送 : 2")
    send("2")
}

demoScope.launch {
    demoFlow.collect {
        println("收集 $it")
        delay(5000)
    }
}

// 输出顺序:
// 发送 : 1
// 发送 : 2
// 收集 : 1 
// 5秒之后打印:收集 : 2

CallbackFlow

创建一个冷流实例,将异步回调转换为流,如按钮单击。我们不能使用简单的Flow,因为emit()它是挂起函数,callbackFlow允许从与函数不同CoroutineContextsend函数或与函数的协程外部发出值trySend

fun demoCallBackFlow(): Flow<Boolean> = callbackFlow {
    val callback = object : DemoCallback() {
        override fun onSuccess() {
            trySend(true)
        }
        override fun onFailre() {
            trySend(false)
        }
    }
    
    demoRegisterFunction(callback)

    awaitClose {
        // 回调结束时执行
        demoUnRegisterFunction(callback)
    }
}

emptyFlow

创建一个空的流

fun demoFunction(nullAbleStr: String?): Flow<String> {
    return if (nullAbleStr.isNullOrEmpty()) {
        emptyFlow<String>()
    } else {
        flow {
            emit("不为空返回值")
        }
    }
  }
}