3

我首先要说我已经阅读了一百万个博客,观看了一千个视频,但我对页面越来越感到困惑。在输入所有这些内容时胡思乱想有助于我解决一些问题。

TL; DR 主要问题是如何为 UI 层和通常(在方法中内联)检索数据的反应性(使用后台线程)对于已经在后台线程上调用您的方法的业务层方法。您的 Repo 和 Dao 是否需要多种方法来执行相同的查询?

@Query("Select * from Product WHERE Product.ProductId = :id")
ProductDb getForId(Integer id);

@Query("Select * from Product WHERE Product.ProductId = :id")
LiveData<ProductDb> getForIdLive(Integer id);

@Query("Select * from Product WHERE Product.ProductId = :id")
Maybe<ProductDb> getForIdRx(Integer id);

使用 MVVM 架构。来自新 Android 架构组件的 ViewModel 实现负责处理生命周期问题,所以让我们使用它。

使用 Room 数据库组件实现的数据库 - 所有设置都完美运行,这就是如何在我的应用程序中检索不同层的数据,这让我很困扰。

我们将举一个简单的例子,通过 Id 从数据库中检索产品。

LiveData 如果您只想在 UI 中显示数据,此选项似乎很好。您的活动或片段创建 ViewModel,设置等待数据的观察者。

// get an instance of the viewmodel
mMyViewModel = ViewModelProviders.of(this).get(MyViewModel.class);

// Setup an observer on the Product.  This will tell us when one is loaded.
final Observer<Product> productObserver = new Observer<Product>() {
    @Override
    public void onChanged(Product product) {
        doSomethingWithProduct(product);
    }
};

然后可以通过调用 ViewModel 中的方法来加载产品,响应被吐出到我们在观察者中设置的 doSomethingWithProduct()

mMyViewModel.getProductById(productId).observe(this,productObserver);

ViewModel 有一个方法

public LiveData<Product> getProductById(int id) {
    return mReferenceDataRepository.loadProductById(id);
}

存储库有一个非常相似的方法

public LiveData<Product> loadProductById(int id) {
    return mProductDao.loadProductById(id);
}

最后是 Room 架构的 Dao 作为一种方法来进行实际的数据库检索。

@Query("SELECT * from Product WHERE ProductId = :id")
LiveData<Product> loadProductById(int id);

我们使用从数据库到 Observer 的 LiveData,一切都很顺利。因为 Dao 是 LiveData,所以检索是在后台线程上完成的,该线程负责处理 Room 吐出的 ANR。对于检索数据以进行简单显示,这条路线似乎很完美。

然而,并非一切都与 UI 有关!

该应用程序比这更复杂。我正在将库存项目添加到库存中,并且基于存储在产品/位置等中的几个业务规则,我可能需要将其放入隔离区或拒绝它。

  • Activity 不应该实现这些业务规则,它的工作是简单地与用户沟通,另外可能有几个 Activity 可以添加库存项目

  • ViewModel 不应该实现这些业务规则,多个活动可能需要相同的规则。

  • 存储库不应该实现这些业务规则——应该吗?

我会在 StockItemBL(业务层)中实现这些规则。AddItemToStock 方法。

现在我需要从数据库加载产品,但我不想要 LiveData<>。我不想以响应式方式加载产品,我不需要在 BusinessLayer 中响应式,当您需要加载多个 Db 表来执行业务逻辑时它就不起作用。我只想要一个好的旧时尚

Product p = mReferenceDataRepository.loadProductById(productId);
Location l = mReferenceDataRepository.loadLocationById(locationId);

if (p.getQuarantine())....

if (l.getIsQuarantine())....

但该方法返回一个 LiveData,而不仅仅是一个 POJO 产品 我现在需要在存储库中使用另一个方法吗?

我也以同样的方式看待 RxJava。
你可以从 Dao 返回一个 Maybe,事实上,Rx 更容易管理异常。但它有同样的问题——你的存储库和 Dao 中是否需要单独的方法。

事实上,使用 Repository 的原因是您可以切换实现。如果您的方法公开 LiveData 或 Maybe 那么您真的可以轻松切换实现吗?

4

0 回答 0