考虑一个显示数据列表的Android应用,让用户深入了解它。在某些时候,用户会对需要在后端堆栈上的多个活动中反映的数据进行更改。实现这一目标的最佳模式是什么?
答案 0 :(得分:3)
您的应用中有一个数据源。它的更新需要反映到多个UI,
您需要以某种方式为所有UI创建单一的事实来源,并在发生事件时反映对它们的更改。
我使用Google新架构组件中的MVVM
和ViewModel
+ LiveData
在我的项目中解决了这个问题。为什么?因为它们是生命周期意识!您可以使用RxJava执行相同的操作。
model layer
它是一个单例,并将数据源公开为LiveData
A.在以下代码中,它将是OrderLiveStore.liveData
。
class OrderLiveStore(
private val orderStore: OrderStore
) {
var liveData: MutableLiveData<List<Order>> = MutableLiveData()
init {
liveData.value = orderStore.items
}
}
view model layer
案例1:您只需将该模型注入视图模型,并将LiveData
A公开给视图。在考虑单例的事实下,连接到该视图模型的所有视图都将获得更新,因为视图模型只是从单例变量返回相同的属性。我使用dagger
管理单身人士。
class OrdersViewModel
@Inject constructor(
orderLiveStore: OrderLiveStore
): ViewModel() {
// expose to the view directly
val orders: LiveData<List<Order>> = orderLiveStore.liveData
}
案例2:您仍然将模型注入视图模型,但在内部,您需要使用Transformations.map
订阅它,并进行处理,并将结果公开给视图层
class OrderViewModel(
orderLiveStore: OrderLiveStore,
private val orderId: String
) : ViewModel() {
// expose to the view after processing it
val order: LiveData<Order> = Transformations.map(orderLiveStore.liveData) {
getNeededOrderFromList(it)
}
private fun getNeededOrderFromList(orderList: List<Order>?): Order? {
// This method will be triggered every time orderStore.liveData gets updated
}
}
你可以看到,在案例1中,我使用匕首进行注射,因为它符合案例。在第2种情况下,我使用自定义参数在视图中创建了视图模型,因为视图模型需要一些额外的信息来从模型层中获取所需的部分。就我而言,它是orderId:String
view layer
现在很简单,无论是片段还是活动,您都会观察到数据源并更新您的用户界面,
orderViewModel.orders.observe(this, Observer {
// update the ui
})
或者更优雅的是,如果您不需要那么多的预处理,可以使用数据绑定将LiveData
从视图模型直接绑定到xml
。
嗯,您只需直接更新model
图层。但该动作将从2层中的一层开始
view
图层(如果是来自用户)view model
图层(如果它是副作用)。 但即使它来自view
,view
仍会调用view model
上的方法,而view model
会调用模型图层上的某些方法,或者您只需更新它在视图模型层中取决于案例(因为你得到了单一的事实来源)。
它有点像Redux模式 - 几乎是单向数据流,每次更改都会在模型层发生并反射回视图模型层,然后冒泡到视图层。很容易推断出你的数据流。
因为现在所有内容都连接到单个事实源(共享模型层),但是以解耦的方式连接。每一层都有自己的工作。
为了让Transformations.map
生效,您需要在视图中observe
结果,否则,来自Transformations.map
的订阅将无效。
答案 1 :(得分:1)