我是否阅读了有关 Flow 的更多信息,我开始认为您可以用与 Flow 类似的内容替换 MutableLiveData switchMap 模式。
您可以通过实现类似的方法来用流替换 LiveData 观察,但我无法想象如何替换 switchMap 部分。
我所说的 switchMap 模式是这样的:
val mutableLiveData: MutableLiveData<SomeClass> = MutableLiveData()
val liveData: LiveData<SomeOtherClass> = mutableLiveData
.switchMap {
//call to repo
}
Run Code Online (Sandbox Code Playgroud)
有没有类似的东西或者我完全错过了一些东西?或者甚至以完全错误的方式思考流程。
当使用 Livedata 作为 Room 中表上的 select* 查询的返回类型时,然后我观察它,如果我更新/插入/删除该表中的条目,我会得到触发器。然而,当我尝试使用 Kotlin Flow 时,我只得到 2 个触发器。
第一个触发器给出一个空值,因为状态流的初始值为空。第二个触发器是 Room 表中的条目列表。
如果我对数据库执行插入/删除操作,我会收到来自 StateFlow 的触发器。但是,如果我更新条目,Stateflow 不会触发。
注意:更新操作在数据库上正常工作。我使用 DB 检查器进行了检查。
数据类和 DAO
@Entity
data class CartItem (
@PrimaryKey
val itemId: Int,
var itemQuantity: Int=1
)
@Dao
interface CartDao {
@Query("SELECT * FROM CartItem")
fun getAllItems(): Flow<List<CartItem>>
@Update
suspend fun changeQuantityInCart(cartItem:CartItem)
@Insert
suspend fun insert(item: CartItem)
@Delete
suspend fun delete(cartItem:CartItem)
}
Run Code Online (Sandbox Code Playgroud)
视图模型
val cartItems: StateFlow<List<CartItem>?> =
repo.fetchCartItems().stateIn(viewModelScope, SharingStarted.Lazily, null)
Run Code Online (Sandbox Code Playgroud)
分段
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
viewModel.cartItems.collect {
Log.e("Update","Update")
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试在我的应用程序中使用 SqlDelight 数据库。
在我的 DAO 中,我有一个名为 getRecipeById 的函数来查询数据库并返回域模型流(Recipe)。下面是该函数的实现:(注:RecipeTable 是表的名称,或者我想我应该将其称为 RecipeEntity)
fun getRecipeById(id: Int): Flow<Recipe> {
return recipeQueries.getRecipeById(id)
.asFlow()
.mapToOne()
.map { recipeTable: RecipeTable ->
recipeTableToRecipeMapper(recipeTable = recipeTable)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的存储库像这样调用这个函数:(注意:recipeLocalDatabase 是我的 DAO)
suspend fun getRecipeById(id: Int): Flow<RecipeDTO> {
val recipeFromDB: Flow<Recipe> = recipeLocalDatabase.getRecipeById(id)
return recipeFromDB.map { recipe: Recipe ->
recipeDTOMapper.mapDomainModelToDTO(recipe)
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的用例层从存储库调用该函数并传递流程:
suspend fun execute(
id: Int
): UseCaseResult<Flow<RecipeDTO>>
{
return try{
UseCaseResult.Success(recipeRepository.getRecipeById(id))
} catch(exception: Exception){
UseCaseResult.Error(exception)
}
}
Run Code Online (Sandbox Code Playgroud)
现在在 ViewModel 中,我正在收集 RecipeDTO 的流程,如下所示:
var recipeForDetailView: MutableState<RecipeDTO> = mutableStateOf( …Run Code Online (Sandbox Code Playgroud) 我最近正在改造Flow我的存储库。
结果密封类
enum class ApiStatus{
SUCCESS,
ERROR,
LOADING
}
sealed class ApiResult <out T> (val status: ApiStatus, val data: T?, val message:String?) {
data class Success<out R>(val _data: R?): ApiResult<R>(
status = ApiStatus.SUCCESS,
data = _data,
message = null
)
data class Error(val exception: String): ApiResult<Nothing>(
status = ApiStatus.ERROR,
data = null,
message = exception
)
data class Loading<out R>(val _data: R?, val isLoading: Boolean): ApiResult<R>(
status = ApiStatus.LOADING,
data = _data,
message = null
)
}
Run Code Online (Sandbox Code Playgroud)
3 …
我正在嵌套启动{}的流程中从数据存储区收集数据。
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
launch {
DataStore.userName.collect {
// it emits string value
Log.e(TAG, it )
}
}
launch {
DataStore.userPhone.collect {
// it emits string value
Log.e(TAG, it )
}
}
launch {
DataStore.userAddress.collect {
// it emits string value
Log.e(TAG, it )
}
}
}
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来收集碎片中的流量?就像在单个 launch{} 块中收集所有数据一样。
嘿,我正在 android 中的 kotlin flow 工作。我注意到我的 kotlin 流程collectLatest调用了两次,有时甚至更多。我尝试过这个答案,但它对我不起作用。我在我的函数中打印了日志,collectLatest它打印了日志。我正在添加代码
MainActivity.kt
class MainActivity : AppCompatActivity(), CustomManager {
private val viewModel by viewModels<ActivityViewModel>()
private lateinit var binding: ActivityMainBinding
private var time = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupView()
}
private fun setupView() {
viewModel.fetchData()
lifecycleScope.launchWhenStarted {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.conversationMutableStateFlow.collectLatest { data ->
Log.e("time", "${time++}")
....
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
ActivityViewModel.kt
class ActivityViewModel(app: Application) : AndroidViewModel(app) {
var conversationMutableStateFlow = MutableStateFlow<List<ConversationDate>>(emptyList()) …Run Code Online (Sandbox Code Playgroud) android kotlin kotlin-coroutines kotlin-flow kotlin-stateflow
如前所述,我想按顺序连接两个流,因此merge行不通。
例子:
val f1 = flowOf(1, 2)
val f2 = flowOf(3, 4)
val f = concatenate(f1, f2) // emits 1, 2, 3, 4
Run Code Online (Sandbox Code Playgroud) 我正在学习 kotlin flow 并慢慢地将我公司应用程序中的代码从 livedata 转换为 kotlin flow。所以我有疑问:
在我的视图模型中,我有这样的 livedata 变量“状态”:
var status: MutableLiveData = MutableLiveData()
我在 MainActivity 中观察到了它。
现在我想用 Flow 做同样的事情。我转换了所有发射/收集部件和其他部件,一切正常,但有一个问题。这是声明我的变量状态的一部分:
var status: MutableStateFlow<Status> = MutableStateFlow() -> 这段代码给出了错误。我需要传递括号中的参数值
所以我必须这样写:
var status: MutableStateFlow<Status> = MutableStateFlow(Status.Failure("adding value even though I don't want to"))
Run Code Online (Sandbox Code Playgroud)
谁能解释一下,有没有什么方法可以像以前一样在 livedata 中初始化它而不提供初始值?谢谢
我想实现具有实时更新的系统(类似于 onSnapshotListener)。我听说这可以用Kotlin Flow来完成。
这是我来自存储库的函数。
suspend fun getList(groupId: String): Flow<List<Product>> = flow {
val myList = mutableListOf<Product>()
db.collection("group")
.document(groupId)
.collection("Objects")
.addSnapshotListener { querySnapshot: QuerySnapshot?,
e: FirebaseFirestoreException? ->
if (e != null) {}
querySnapshot?.forEach {
val singleProduct = it.toObject(Product::class.java)
singleProduct.productId = it.id
myList.add(singleProduct)
}
}
emit(myList)
}
Run Code Online (Sandbox Code Playgroud)
还有我的视图模型
class ListViewModel: ViewModel() {
private val repository = FirebaseRepository()
private var _products = MutableLiveData<List<Product>>()
val products: LiveData<List<Product>> get() = _produkty
init {
viewModelScope.launch(Dispatchers.Main){
repository.getList("xGRWy21hwQ7yuBGIJtnA")
.collect { items ->
_products.value …Run Code Online (Sandbox Code Playgroud)