我使用 MVVM 架构设置我的应用程序。我要解决的问题是根据两个查询参数(在本例中为起点和终点)触发 api 调用,这是动态的并实时更新。当更新这些值中的任何一个时,应检查两者都不为空,然后根据这两个值进行 api 调用。
我一直在使用 MediatorLiveData
和 Transformations.switchMap()
,但一直无法获得运行良好的解决方案。尝试使用 MediatorLiveData:
class MyViewModel(val repository: AppRepository) : ViewModel() {
val origin = MutableLiveData<Location>()
val destination = MutableLiveData<Location>()
val directions = MediatorLiveData<DrivingDirections>()
init {
directions.addSource(origin) { origin ->
if (origin != null && destination.value != null) {
directions.value = // problem here
// I want to make a call to something like
// repository.getDirections(origin, destination), but this comes
// back as LiveData<Directions> so *can't* set it to directions.value
// I, in effect, want to make directions = repository.getDirections(origin, destination),
// but then I lose the Mediator functionality
}
}
directions.addSource(destination) {
// as above
}
}
}
因此,尝试使用 switchMap,我创建了一个粗略的 OriginAndDestination
对象,然后观察了它的变化。
class myViewModel(val repository: AppRepository) : ViewModel() {
val originAndDestination = MutableLiveData<OriginAndDestination>()
val directions: LiveData<Directions>
init {
directions = Transformations.switchMap(originAndDestination) { originAndDestination ->
// probably should do some checks that both origin and destination are not null,
// so this switch map could return null? How do I guard against null in a switch map?
repository.getDirections(originAndDestination.origin, originAndDestination.destination)
}
}
fun setOrigin(location: Location) {
// bit of problem code here... need to retrieve the current value of
// originAndDestination.value, then update the 'origin' property,
// then set it to the liveData value again to trigger the switchMap, above... while checking that the value isn't null in the first place...
// something like:
val tempValue = originAndDestination.value
if (tempValue != null) {
// update tempValue.origin
} else {
// create a new OriginAndDestination object?
}
// just feels really messy
}
fun setDestination(location: Location) {
// As above
}
}
对所有评论表示抱歉,但它突出了一些痛点和挫败感。我会以错误的方式处理这件事吗? Origin
和 Destination
从 UI 字段设置。
最佳答案
这比 MVVM 更像是 MVI,但这是我处理它的方式:
data class myViewState(
val origin: Location,
val destination: Location,
val directions: DrivingDirections
)
class myViewModel(val repository: AppRepository) : ViewModel() {
private val _states = MediatorLiveData<myViewState>()
val states: LiveData<myViewState> = _states
private val lastSource: LiveData<myViewState>? = null
fun updateLocations(origin: Location, destination: Location) {
lastSource?.let { _states.removeSource(lastSource) }
lastSource = repository.getDirections(origin, destination)
_states.addSource(lastSource) { directions ->
_states.value = myViewState(origin, destination, directions)
}
}
}
(如果幸运的话,我们可以去掉 lastSource
sometime in the future )
然后,您的 UI 层会观察状态
,并根据位置和方向更新其 UI。
这可能不适合您的架构,但它可能会给您一些想法。
关于android - 如何设置 LiveData 以根据多个参数执行搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56059225/