有一个设置屏幕(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个字段的活动,该活动观察MutableLiveData
中的10个ViewModel
。在每个字段的onClick
上,打开一个对话框来编辑/插入文本。在对话框的onPositiveButton
上,将调用相应字段的观察者。
该活动实现了OnRequestProgressListener
,以根据异步请求的进度显示和隐藏对话框。
上述设计似乎不正确。我可以指出一些:
MutableLiveData
中ViewModel
; DataRepository
中SharedPreferences
的存储库。ViewModel
接收侦听器,以传递给执行异步请求的类,这些请求使用这些侦听器来通知视图。全部位于ViewModel
中间。这是正确的解决方案吗?如果不是,我认为不是,应该如何设计正确的解决方案?
答案 0 :(得分:3)
- 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中使用它,并为其提供进度,并且您的活动需要订阅它才能获取进度信息。
使用这种方法,您可以避免内存泄漏。
答案 1 :(得分:1)
您可以使用一个Settings
数据类,其中包含封装您的数据的字符串,整数和获取器。
一个MutableLiveData<Settings>
足以跟踪更改并将更改传递到UI。如果使用TextViews和EditTexts,则使用数据绑定也不需要样板代码。要使数据绑定与LiveData
一起使用,您需要使用setValue()
中定义的方法来调用LiveData
中的ViewModel
。我做了an example的数据绑定是如何工作的,而不是LiveData
的工作。
您可以查看my answer,了解如何使用具有可变对象的LiveData
并更新UI,而无需任何锅炉代码和不必要的MutableLiveDatas或将MutableLiveData<Object>
转换为MutableLiveData<String>
或{ {1}}。
如果您可以共享布局文件,我可以发布更具体的答案。