对于具有多个字段的活动,应如何实现ViewModel

Mat*_*res 5 architecture android mvvm android-livedata android-architecture-components

问题

有一个SettingsActivity带有大约10个文本字段和3个按钮的设置屏幕()。文本字段在onClick打开对话框以插入/编辑文本时,其内容保存在中SharedPreferences。这些按钮执行异步请求以检索内容并将其保存在其他位置。在请求期间,将显示一个对话框以通知进度。

初始解决方案

资料储存库

基本上,是SharedPreferences的包装,它具有10个getter和10 setter,每个字段一个。在上get[field_name],从上DataRepository获取值,SharedPreferences然后在上set[field_name]提交SharedPreferences

视图模型

ViewModel,其具有10度MutableLiveData的目的,一个用于每个字段。此类实现了LifecycleObserver有关SettingsActivity生命周期的信息,因此可以从上加载存储库中onCreate的字段并将字段保存到上的存储库中onDestroy

还有3种方法来执行由上述3个按钮触发的3个异步请求。每个方法都接收一个OnRequestProgressListener实例,该实例将传递给发出异步请求的类,该类将用于将视图通知进度。

视图

有10场的活动,即观察10 MutableLiveDataViewModel。在onClick每个字段中,打开一个对话框以编辑/插入文本。在onPositiveButton对话框的上,将调用相应字段的观察者。

该活动OnRequestProgressListener根据异步请求的进度实现显示和隐藏对话框。

最初的解决问题

上述设计似乎不正确。我可以指出一些:

  • 10 MutableLiveDataViewModel;
  • 10个getter和10个setter DataRepository;
  • 的存储库SharedPreferences
  • 所述ViewModel接收听众传递给做,采用这些听众来通知视图异步请求的类。都ViewModel在中间。

正确的解决方案

那是正确的解决方案吗?如果不是,我认为不是,应该如何设计正确的解决方案?

Tpo*_*6oH 5

  • ViewModel 中的 10 个 MutableLiveData;

这完全没问题,如果您有 10 个独立的数据,您可以为每个数据提供一个 LiveData。

  • SharedPreferences 的存储库。

存储库应该是对数据层的抽象,允许您轻松切换实现。因此,理论上拥有共享首选项的存储库是可以的。

但是在您的情况下,如果存储库所做的唯一一件事就是转发调用,SharedPreferences因为将存储解决方案从共享首选项切换到其他东西的可能性非常低,我会摆脱存储库并直接使用 SharedPreferences 来简化代码。

  • DataRepository 中有 10 个 getter 和 10 个 setter;

同样,如果您在类中存储了 10 条数据并希望从外部访问它,您应该使用属性模式,这会导致 Java 中的 getter 和 setter。在 Kotlin 中,虽然您不需要明确地编写 getter 和 setter。此外,如果您决定删除 DataRepository,您将不需要该代码。

  • ViewModel 接收侦听器以传递给执行异步请求的类,这些类使用这些侦听器通知视图。所有这些都带有中间的 ViewModel。

这听起来有点错误,如果你在你的活动中创建一个监听器,你很可能会不小心使用具有活动引用的匿名类,将它传递给ViewModel并导致内存泄漏。您不应将活动引用传递给ViewModel. 正确的通信方式是通过 LiveData。您需要创建一个将发布进度的 LiveData,在 ViewModel 中使用它,为其提供进度,并且您的活动需要订阅它以获取进度信息。使用这种方法,您可以避免内存泄漏。