简体   繁体   English

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

[英]How do I notify multiple Activities and Fragments of a dataset change?

Consider an Android app that displays lists of data and lets the user drill down into it. 考虑一个显示数据列表并允许用户向下钻取的Android应用。 At some point the user makes a change to the data that needs to be reflected in more than one Activity on the back stack. 在某些时候,用户对需要在后台堆栈上的多个活动中反映的数据进行更改。 What is the best pattern for achieving this? 实现此目标的最佳模式是什么?

First, let's check the cases. 首先,让我们检查一下情况。

There is a data source in your app. 您的应用中有一个数据源。 And its updates needs to reflect to multiple UI, 其更新需要反映到多个用户界面,

  • case 1: some UI maybe just need the whole data source 情况1:某些UI可能只需要整个数据源
  • case 2: some UI needs to process the data first before showing on the UI 情况2:某些用户界面需要先处理数据,然后才能显示在用户界面上

You need to somehow create a single source of truth for all the UI and reflect the changes to them when something happens. 您需要以某种方式为所有UI创建真实的来源,并在发生某些情况时将更改反映给他们。

I solved this problem in my project by using MVVM and ViewModel + LiveData from google's new architecture component. 我通过使用MVVM和来自Google新架构组件的ViewModel + LiveData解决了这个问题。 Why? 为什么? Because they are life cycle aware! 因为他们知道生命周期! You can use RxJava to do the same thing. 您可以使用RxJava做同样的事情。

1. model layer 1. model layer

It's a singleton, and expose the data source as a LiveData A. In the following code, it will be OrderLiveStore.liveData . 这是一个单例,并将数据源公开为LiveData 。在以下代码中,它将为OrderLiveStore.liveData

    class OrderLiveStore(
        private val orderStore: OrderStore
    ) {
        var liveData: MutableLiveData<List<Order>> = MutableLiveData()

        init {
            liveData.value =  orderStore.items
        }

    }

2. view model layer : 2. view model layer

  • case 1: You just inject that model to the view model, and expose the LiveData A to the view. 情况1:您只需将该模型注入视图模型,然后将LiveData A暴露给视图。 Underneath considering the fact of singleton, all views which connect to this view model will get the update, because the view model simply just returns the same property from a singleton variable. 在考虑单例事实的情况下,连接到该视图模型的所有视图都将获得更新,因为视图模型仅从单例变量中返回相同的属性。 I manage the singleton by using dagger . 我使用dagger管理单例。

     class OrdersViewModel @Inject constructor( orderLiveStore: OrderLiveStore ): ViewModel() { // expose to the view directly val orders: LiveData<List<Order>> = orderLiveStore.liveData } 
  • case 2: You still inject the model to the view model, but inside, you need to subscribe to it using Transformations.map , and do your processing, and expose the result to the view layer 情况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 } } 

You can see that in case 1, I use dagger to inject because it fits the case. 您可以看到,在情况1中,我使用匕首进行注入,因为它适合情况。 In case 2, I created the view model in view with custom parameter, because the view model needs some extra information to grab the needed pieces from the model layer. 在案例2中,我使用自定义参数在视图中创建了视图模型,因为视图模型需要一些额外的信息来从模型层获取所需的片段。 In my case, it is a orderId:String 就我而言,这是一个orderId:String

3. view layer 3. view layer

Now it's simple, be it a fragment or an activity, you observe that data source and update your UI, 现在很简单,无论是片段还是活动,您都可以观察到该数据源并更新UI,

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

or more elegantly, you can bind the LiveData from view model directly to the xml with data binding if you don't need that much pre-processing. 或更优雅地说,如果不需要太多预处理,则可以使用数据绑定将LiveData从视图模型直接绑定到xml

4. What about the CRUD 4.关于CRUD

Well, you just update the model layer DIRECTLY. 好吧,您只需直接更新model层。 But the action will be started from one of the 2 layers 但动作将从两层之一开始

  • view layer (if it's from a user) view层(如果来自用户)
  • view model layer (if it's a side-effect). view model层(如果有副作用)。

But even it's from the view , the view will still call methods on view model , and view model will call some methods on model layer or you can simply update it in the view model layer depends on the cases(because you get the single source of truth). 但是即使是从viewview仍将调用view model上的方法, view model将在模型层上调用某些方法,或者您可以根据情况在视图模型层中简单地对其进行更新(因为您获得了真相)。

It's kind of like Redux pattern - a nearly unidirectional data flow, where every change will happen at model layer and reflect back to view model layer, then bubble up to view layer. 这有点像Redux模式-几乎是单向的数据流,其中每个更改都将在模型层发生并反射回视图模型层,然后冒泡到视图层。 It's easy to reason about your data flow. 关于数据流的推理很容易。

5. And the result will be what you want. 5.结果将是您想要的。

Because everything is now connected to a single source of truth(a shared model layer), but, in a decoupled manner. 因为现在所有事物都连接到单个真理源(共享模型层),但是以分离的方式进行。 Every layer does its own job. 每个层都有自己的工作。

6. One more tip 6.另一个提示

In order to get Transformations.map to work, you need to observe the result in the view, otherwise, that subscription from Transformations.map will not work at all. 为了使Transformations.map正常工作,您需要在视图中observe结果,否则,从Transformations.map订阅将根本无法工作。

You can put your shared data in a Service , then in your fragment/activity's onResume methods you can get updated data from there. 您可以将共享数据放在Service中 ,然后在片段/活动的onResume方法中从那里获取更新的数据。

To update your current fragment/activity you can fire an event when you update data in the Service, registering your fragment/activity to catch it and consequently update your showed data. 要更新您当前的片段/活动,您可以在更新服务中的数据时触发一个事件,注册您的片段/活动以捕获该片段/活动,从而更新您显示的数据。 You could use OttoBus to achieve this goal 您可以使用OttoBus实现此目标

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有多个活动和片段的Android清单已严重损坏! 我该如何解决? - Android Manifest with multiple activities and fragments are severely corrupted! How do I fix them? 如何在Android Studio中的多个活动/片段中重用相同的xml背景布局? - How do I reuse the same xml background layout in multiple activities/fragments in Android Studio? 如何使用片段处理多个活动? - How to handle multiple activities with fragments? 如何使用EditText在片段和活动之间传递信息? - How do I pass info between fragments and activities with an EditText? 按钮的多个活动或片段 - Multiple activities or fragments for buttons 如何在多个片段中设置SupportSupportBar()? - How do I setSupportActionBar() in multiple fragments? 如何通知不活动的活动? - How to notify inactive activities? 如何在不使用片段的情况下在多种类型的活动上获得相同的抽屉布局? - How can I get the same drawerLayout on multiple types of activities without using fragments? 我如何使用活动数组列表而不是使用多个片段 - how can i use array list of activities instead of using multiple fragments Android 中具有多个片段的多个活动 - Multiple Activities with multiple fragments in Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM