发射和发射源与 LiveData 有什么区别?(如在实时用例中)

San*_*Sur 17 android android-livedata android-architecture-components android-jetpack kotlin-coroutines

emit接受data类而emitSource接受LiveData<T>( T -> data)。考虑以下示例:-我有两种类型的调用:-

suspend fun getData(): Data // returns directly data
Run Code Online (Sandbox Code Playgroud)

而另一个;

suspend fun getData(): LiveData<Data> // returns live data instead
Run Code Online (Sandbox Code Playgroud)

对于第一种情况,我可以使用:-

liveData {
   emit(LOADING)
   emit(getData())
}
Run Code Online (Sandbox Code Playgroud)

我的问题:使用上述方法可以解决我的问题,为什么我们还需要emitSource(liveData)

任何使用该emitSource方法的好用例都会清楚地表明!

Pet*_*ter 27

正如您所提到的,我认为它不能解决您陈述的问题中的任何问题,但我通常这样使用它:

如果我想在从远程获取新数据时从数据库向用户显示缓存数据,只发出它看起来像这样:

liveData{
    emit(db.getData())
    val latest = webService.getLatestData()
    db.insert(latest)
    emit(db.getData())
}
Run Code Online (Sandbox Code Playgroud)

但是使用emitSource,它看起来像这样:

liveData{
    emitSource(db.getData())
    val latest = webService.getLatestData()
    db.insert(latest)
}
Run Code Online (Sandbox Code Playgroud)

不需要再次调用发射,因为 liveData 已经有一个源。


Myk*_*Myk 10

据我了解emit(someValue),类似于myData.value = someValueemitSource(someLiveValue)类似于myData = someLiveValue. 这意味着只要您想设置一次值就可以使用emit,但是如果您想将实时数据连接到另一个实时数据值,则可以使用emit 源。一个例子是从对房间的调用(使用emitSource(someLiveData))发出实时数据,然后执行网络查询并发出错误(使用emit(someError))。


San*_*Sur 9

我发现了一个真实的用例,它描述emitSourceemit我现在在生产中多次使用的用法。:D 用例:

假设您有一些由 some 返回的用户数据(User其中包含一些字段,例如userId, userNameApiService

User型号:

data class User(var userId: String, var userName: String)
Run Code Online (Sandbox Code Playgroud)

userName是由视图/活性所需绘制UI。而且userId是用来做其他的API调用,它返回的UserData一样profileImageemailId

UserData型号:

data class UserData(var profileImage: String, var emailId: String)
Run Code Online (Sandbox Code Playgroud)

这可以使用在内部来实现emitSource 由布线两个liveDataViewModel这样的:

User 实时数据 -

val userLiveData: LiveData<User> = liveData {
   emit(service.getUser())
}
Run Code Online (Sandbox Code Playgroud)

UserData 实时数据 -

val userDataLiveData: LiveData<UserData> = liveData {
   emitSource(userLiveData.switchMap {
       liveData {
           emit(service.getUserData(it.userId))
       }
   })
}
Run Code Online (Sandbox Code Playgroud)

因此,在活动/视图可以调用getUser()getUserData(userId)将被自动触发通过内部switchMap

您无需通过传递 id手动调用getUserData(id)

这是一个简单的例子,假设有一系列依赖任务需要一个接一个地执行,每个任务都在活动中被观察到。emitSource进来handy


ins*_*ing 6

使用emitSource(),您不仅可以发出单个值,还可以将您的LiveData 附加到另一个LiveData 并开始从它发出。无论如何,每个emit() 或emitSource() 调用都会删除之前添加的源。

var someData = liveData {
    val cachedData = dataRepository.getCachedData()
    emit(cachedData)

    val actualData = dataRepository.getData()
    emitSource(actualData)
}
Run Code Online (Sandbox Code Playgroud)

观察 someData 对象的 Activity 将快速接收设备上的缓存数据并更新 UI。然后,LiveData 本身将负责发出网络请求并用新的实时数据流替换缓存的数据,这最终将触发 Activity 观察器并使用更新的信息更新 UI。

来源:探索 Android 上的新协程和生命周期架构组件集成