kotlin 通过“StateFlow”发出初始值后,Android ViewModel无法收集

g6ll5ycj  于 2023-03-09  发布在  Kotlin
关注(0)|答案(1)|浏览(239)

我正在将我的Android项目迁移到Jetpack Compose。为此,我从Compose的一个单独的单例类中发出StateFlow事件,并在ViewModel中发出collect事件。但是,在发出一个事件后,不会从ViewModel中的流收集任何其他事件:
1.从我的单例类中发出:

/**
  * Class that emits bottom sheet events (expanded, collapsed, etc.).
  */
@Singleton
class BottomSheetEventProducer {
    private val _eventsFlow = MutableStateFlow<SheetEvent>(SheetEvent.Collapsed)
    val eventsFlow: Flow<SheetEvent> = _eventsFlow

    fun produceEvent(event: String) {
        var sheetEvent: SheetEvent = SheetEvent.Collapsed

        if (event.contains(SheetEvent.Collapsed.Const().value)) {
            sheetEvent = SheetEvent.Collapsed
        } else if (event.contains(SheetEvent.Expanded.Const().value)) {
            sheetEvent = SheetEvent.Expanded
        }

        Log.i("BottomSheetEventsSingleton", "produceEvent: $sheetEvent")
        _eventsFlow.value = sheetEvent
    }
}

1.在视图模型中收集:

@HiltViewModel
    class FarmViewModel @Inject constructor(
        private val bottomSheetEvents: BottomSheetEvents
    ) : ViewModel() {
    init {
            viewModelScope.launch {
                bottomSheetEvents.eventsFlow
                    .collect { event ->
                        Log.i("FarmViewModel", "flow event: $event)")
                    }
            }
        }

collect中的Log.i只显示初始值,之后什么也不显示。

rur96b6h

rur96b6h1#

您似乎希望使用函数创建一个事件,然后在视图模型中查看生成的事件。但是,不清楚这些事件应在何时生成。下面是一个与您的示例类似的示例:
在本例中,创建了一个数据源作为事件类的等价物,它使用共享流每三秒钟生成一个随机字符串。

object DataSource {
private val _myStringFlow = MutableSharedFlow<String>()

init {
    CoroutineScope(Dispatchers.Default).launch {
        while (true) {
            delay(3000)
            _myStringFlow.emit(generateRandomString())
        }
    }
}

fun getMyString(): Flow<String> = _myStringFlow

private fun generateRandomString(): String {
    val alphabet = ('a'..'z').toList()
    return (1..5)
        .map { alphabet.random() }
        .joinToString("")
}}

然后,您可以在视图模型中收集生成的字符串,如下所示:

class MyViewModel @Inject constructor(
private val dataSource: DataSource): ViewModel() {

private val _myString = MutableLiveData<String>()
val myString: LiveData<String> = _myString

init {
    viewModelScope.launch {
        dataSource.getMyString().collect { myString ->
            _myString.value = myString
        }
    }
}}

相关问题