我首先要说我已经阅读了一百万个博客,观看了一千个视频,让我对这个页面感到更加困惑。在输入所有这些内容时,莫名其妙地帮助我工作了一些事情。
TL; DR 主要问题是如何为UI层反应性地(使用后台线程)检索数据并且通常(在方法中内联)用于已在后台线程上调用方法的业务层方法。做你的回购&& 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,设置一个等待数据的Observer。
// 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中的方法来加载产品,响应是spat out to 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);
}
最后是房间架构的Dao作为进行实际数据库检索的方法。
@Query("SELECT * from Product WHERE ProductId = :id")
LiveData<Product> loadProductById(int id);
我们正在使用从数据库到观察者的LiveData,一切都很有效。因为Dao是LiveData,所以检索是在后台线程上完成的,后台线程负责处理由房间吐出的ANR。为了检索简单显示的数据,这条路线似乎很完美。
然而,并非一切都与UI有关!
应用程序比这更复杂。我将库存商品添加到库存中,并根据存储在产品/位置等中的多个业务规则,我可能需要将其置于隔离区或拒绝它。
活动不应该实施这些业务规则,其工作是 只需与用户沟通,另外可能有几个活动可以添加库存项目
ViewModel不应该实现这些业务规则,这是相同的规则 可能需要多个活动。
知识库不应该实现这些业务规则 - 应该吗?
我在StockItemBL(业务层)中实施这些规则。 AddItemToStock方法。
现在我需要从数据库加载产品,但我不想要LiveData&lt;&gt;。我不想以反应方式加载产品,我不需要在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中使用单独的方法。
实际上,使用存储库的原因是您可以切换实现。如果您的方法暴露了LiveData或Maybe,那么您真的可以轻松地切换实现吗?