问题
有一个设置屏幕 (SettingsActivity
),其中包含大约 10 个文本字段和 3 个按钮。在 onClick
上打开对话框以插入/编辑文本的文本字段将其内容保存在 SharedPreferences
中。这些按钮执行异步请求以检索内容并保存在其他地方。在请求期间,会显示一个对话框以通知进度。
初步解决方案
数据存储库
基本上是 SharedPreferences 的包装器,它有 10 个 getter 和 10 个 setter,每个字段一个。在 get[field_name]
上,DataRepository
从 SharedPreferences
获取值,在 set[field_name]
上,它提交给 SharedPreferences
。
View 模型
一个 ViewModel
,它有 10 个 MutableLiveData
对象,每个字段一个。此类实现 LifecycleObserver
以了解 SettingsActivity
生命周期,因此它可以在 onCreate
上从存储库加载字段并将字段保存到存储库在 onDestroy
上。
还有 3 种方法可以执行由提到的 3 个按钮触发的 3 个异步请求。每个方法接收一个 OnRequestProgressListener
实例,该实例被传递给发出异步请求的类,用于通知 View 有关进度。
查看
一个有 10 个字段的 Activity ,从 ViewModel
观察 10 个 MutableLiveData
。在每个字段的 onClick
上,将打开一个对话框以编辑/插入文本。在对话框的onPositiveButton
上,调用对应字段的观察者。
该 Activity 实现了 OnRequestProgressListener
以根据异步请求进度显示和隐藏对话框。
初始解题
上面描述的设计似乎不正确。我可以指出一些:
ViewModel
中的 10 个MutableLiveData
;DataRepository
中有 10 个 getter 和 10 个 setter;SharedPreferences
的存储库。ViewModel
接收监听器以传递给执行异步请求的类,这些异步请求使用这些监听器通知 View 。中间有ViewModel
。
正确的解决方案
这是正确的解决方案吗?如果不是,我相信不是,应该如何设计正确的解决方案?
最佳答案
- 10 MutableLiveData in the ViewModel;
这完全没问题,如果您有 10 个独立的数据,您可以为每个数据创建一个 LiveData。
- A repository for SharedPreferences.
存储库应该是对数据层的抽象,使您可以轻松切换实现。因此,在理论上拥有共享首选项的存储库是可以的。
但在你的情况下,如果存储库唯一做的是将调用转发到 SharedPreferences
因为将存储解决方案从共享首选项切换到其他东西的可能性非常低,我会摆脱存储库并直接使用 SharedPreferences 以简化代码。
- 10 getters and 10 setters in the DataRepository;
同样,如果您在类中存储了 10 条数据并希望从外部访问它,您应该使用属性模式,这会导致 Java 中的 getter 和 setter。尽管在 Kotlin 中,您不需要显式编写 getter 和 setter。 此外,如果您决定删除 DataRepository,您将不需要该代码。
- The ViewModel receives listeners to pass to the classes that do the async requests which use these listeners to notify the view. All with the ViewModel in the middle.
这听起来有点不对,如果你在你的 Activity 中创建一个监听器,你很可能会不小心使用引用 Activity 的匿名类,将它传递给 ViewModel
并得到内存泄漏。
您不应将 Activity 引用传递给 ViewModel
。
正确的通信方式是通过 LiveData。您需要创建一个将发布进度的 LiveData,在 ViewModel 中使用它,为其提供进度,并且您的 Activity 需要订阅它以获取进度信息。
使用这种方法,您可以避免内存泄漏。
关于android - 应该如何为具有多个字段的 Activity 实现 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51307249/