如何使用挂起函数作为参数在视图模型中初始化流

How to initialize a flow in viewmodel with a suspend function as parameter

我正在使用房间数据库和数据存储。 这是我的代码

视图模型

@HiltViewModel
class SubscriptionViewModel @Inject constructor(
    private val userDataStore: UserDataStore,
    private val walletDao: WalletDao
) : ViewModel() {

val flow: Flow<List<Transaction>> = walletDao.getAllTransactions(userDataStore.getId()) 
 // This shows an error as userDataStore.getId() is a suspend function in DataStore


 init {
        viewModelScope.launch(IO) {
            getWalletAmount()
        }
    }
}

数据存储

 suspend fun getId(): String {
        val preferences = dataStore.data.first()
        return preferences[USER_ID] ?: ""
    }

WalletDao

 @Query("SELECT * FROM recent_transactions where user_id=:user_id")
    fun getAllTransactions(user_id: String): Flow<List<Transaction>>

问题是我无法初始化流程。我尝试使用 lateinit 在 init{ } 块中初始化它,但是在片段中访问时它崩溃了,说流尚未初始化。

任何解决方案都会有所帮助。

据我所知,您可以在变量中调用 suspend fun,它必须在 init 或函数中 还有一个解决方案

@HiltViewModel
class SubscriptionViewModel @Inject constructor(
    private val userDataStore: UserDataStore,
    private val walletDao: WalletDao
) : ViewModel() {
        
    val flow= MutableStateFlow<List<Transcation>>(listOf())
       
    // then add value in init or anywhere 
    init {
        viewModelScope.launch(IO) {
            flow.emit() // add value here
        }
    }
}

您可以将其包装在流生成器中。

val flow: Flow<List<Transaction>> = flow {
    val source = walletDao.getAllTransactions(userDataStore.getId())
    emitAll(source)
}

如果你想让它pre-load(甚至在任何东西收集流量之前就开始获取第一个值),那么你应该通过添加它把它变成一个 SharedFlow:

.shareIn(viewModelScope, SharingStarted.Eagerly, replay = 1)