如何通知多个活动和片段数据集更改?



考虑一个显示数据列表并让用户向下钻取的Android应用程序。在某些时候,用户对需要反映在后退堆栈上的多个Activity 中的数据进行更改。实现这一目标的最佳模式是什么?

首先,让我们检查一下案例。

应用中有一个数据源。并且它的更新需要反映到多个UI,

  • 情况 1:某些 UI 可能只需要整个数据源
  • 情况 2:某些 UI 需要先处理数据,然后才能显示在 UI 上

您需要以某种方式为所有 UI 创建单一事实来源,并在发生某些事情时反映对它们的更改。

我通过使用 google 新架构组件中的MVVMViewModel+LiveData在我的项目中解决了这个问题。为什么?因为他们有生命周期意识!你可以使用RxJava来做同样的事情。

1.model layer

它是一个单一实例,并将数据源公开为LiveDataA。在下面的代码中,它将OrderLiveStore.liveData

class OrderLiveStore(
private val orderStore: OrderStore
) {
var liveData: MutableLiveData<List<Order>> = MutableLiveData()
init {
liveData.value =  orderStore.items
}
}

2.view model layer

  • 情况 1:您只需将该模型注入视图模型,然后将LiveDataA 公开给视图。在考虑单一实例的事实之下,连接到此视图模型的所有视图都将获得更新,因为视图模型只是从单一实例变量返回相同的属性。我通过使用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中,我使用dagger注射,因为它适合这种情况。在案例 2 中,我使用自定义参数在视图中创建了视图模型,因为视图模型需要一些额外的信息才能从模型层中获取所需的部分。就我而言,这是一个orderId:String

3.view layer

现在很简单,无论是片段还是活动,您观察该数据源并更新您的 UI,

orderViewModel.orders.observe(this, Observer {
// update the ui
})

或者更优雅地说,如果您不需要太多的预处理,则可以使用数据绑定将视图模型中的LiveData直接绑定到xml

4. 克鲁德呢

好吧,您只需直接更新model层。但是操作将从 2 层之一开始

  • view图层(如果来自用户)
  • view model层(如果是副作用)。

但即使它来自viewview仍然会在view model上调用方法,view model会在模型层上调用一些方法,或者你可以简单地在视图模型层中更新它取决于情况(因为你得到了单一的事实来源)。

这有点像 Redux 模式 - 一种几乎单向的数据流,其中每个更改都将发生在模型层并反射回视图模型层,然后冒泡到视图层。很容易推断数据流。

5.结果将是你想要的。

因为现在一切都连接到单一事实来源(共享模型层),但以解耦的方式。每一层都有自己的工作。

6. 再提一个提示

为了使Transformations.map正常工作,您需要在视图中observe结果,否则,来自Transformations.map的订阅将根本不起作用。

您可以将共享数据放入服务中,然后在片段/活动的onResume方法中,您可以从那里获取更新的数据。

要更新当前片段/活动,您可以在更新服务中的数据时触发事件,注册片段/活动以捕获它,从而更新显示的数据。您可以使用OttoBus来实现这一目标

最新更新