gpt4 book ai didi

java - MVVM with Retrofit - 如何处理 Repository 中的大量 LiveData?

转载 作者:行者123 更新时间:2023-12-04 11:06:53 26 4
gpt4 key购买 nike

我正在关注这个关于使用 MVVM 和 Retrofit 的教程
https://medium.com/@ronkan26/viewmodel-using-retrofit-mvvm-architecture-f759a0291b49
用户将 MutableLiveData 放置在 Repository 类中的位置:

public class MovieRepository {
private static final ApiInterface myInterface;
private final MutableLiveData<EntityMovieOutputs> listOfMovies = new MutableLiveData<>();

private static MovieRepository newsRepository;

public static MovieRepository getInstance(){
if (newsRepository == null){
newsRepository = new NewsRepository();
}
return movieRepository;
}

public MovieRepository(){
myInterface = RetrofitService.getInterface();
}
我正在构建一个简单的应用程序,我注意到我的存储库类很快被大量 MutableLiveData 对象填充。这实际上是实现 MVVM、LiveData 和 Repository 模式的正确方法吗?
enter image description here
编辑 1:________________________________________________
我创建了一个 AdminLiveData仅保存 LiveData 并具有 getter 的对象。
enter image description here
但是我如何获得对 ViewModel 的引用在我的 AdminRepo类,以便我可以通知 LiveData当 Retrofit Network 调用完成时在 ViewModel 内部?
private AdminService  adminService;

public AdminRepo(Application application) {
BaseApplication baseApplication = (BaseApplication) application;
RetrofitClient client = baseApplication.getRetrofitClient();
adminService = client.getRetrofit().create(AdminService.class);

//AdminViewModel viewModel = (AdminViewModel) ....
// Not sure how to get reference to the viewmodel here so I can get the
// LiveData object and call postValue after the retrofit calls
}

public void getFirstPageMembers(int offset, int limit) {
adminService.getUsersPaginitation(offset, limit).enqueue(new Callback<List<UserInfo>>() {
@Override
public void onResponse(@NonNull Call<List<UserInfo>> call, @NonNull Response<List<UserInfo>> response) {
if (response.body() != null) {
//firstPageLiveData.postValue(response.body());
//Since I create the LiveData inside the ViewModel class
//instead, how do I get reference to the ViewModel's LiveData?
}
}

@Override
public void onFailure(@NonNull Call<List<UserInfo>> call, @NonNull Throwable t) {
//firstPageLiveData.postValue(null);
}
});
}
AdminViewModel :
public class AdminActivityViewModel extends AndroidViewModel {

private AdminRepo repo;

private AdminLiveData adminLiveData = new AdminLiveData();

public AdminActivityViewModel(@NonNull Application application) {
super(application);

repo = new AdminRepo(application);
}
我如何获得对 AdminViewModel 的引用从我的内部 AdminRepo类(class)?

最佳答案

存储库和 View 模型
android 项目中的 Repository 对象应该被认为是通往外部世界的门户。与持久性设施(网络、SQLite、共享首选项)的通信发生在这一层。因为传入的数据不应该符合 android 环境。例如,传入 DTO 中的字符串日期字段应使用本地日期时间转换为日期对象,您可能需要将来自服务器的数据保存到本地数据库。此外,其他与数据相关的任务可以在该层执行,例如在内存中缓存。
ViewModel 表示用户界面中显示的数据。该层中的数据应该准备好在屏幕上呈现。例如,一个 View 可能需要来自两个不同 HTTP 请求的数据,您应该在该层合并传入数据。 (不过,你可以进一步分离职责。如果这两个请求是单个任务或目的的一部分,你可以在用例层做这个操作。)从android的角度来看, View 模型有更多的责任,比如防止数据被破坏在配置更改中。在 View 模型中,建议通过 LiveData 将数据呈现给 View 层。这是因为 LiveData 保持数据的最后状态并且它知道 View 层的生命周期(如果它使用得当)。
Repository 和 ViewModel 之间的通信
首先,存储库层必须不知道任何 View 模型的存在,因此您不应该在存储库层中保留 View 模型的引用。有一些原因,

  • 大多数情况下,用于一组交互的单个存储库对象足以满足整个应用程序的需求。如果保留 View 模型的引用,则会导致内存泄漏。
  • 如果 repo 层中使用的服务器端 API、本地存储和其他组件设计良好,则与 View 模型相比,repository 层不太容易发生变化。
  • 存储库层的职责是从某处获取数据,因此这意味着它与 View 相关层无关。

  • 当然,我们需要某种对 View 模型的引用以在请求完成时通知它,但我们应该以系统的方式隐式地执行此操作,而不是直接引用。
    回电:这是将数据发送回 View 模型的旧时尚方式。在您的代码库中广泛使用回调会导致不想要的回调 hell 。此外,结构化取消机制很难使用回调实现。
    实时数据:乍一看,它似乎非常适合此目的,但事实并非如此。原因可以列举如下
  • LiveData 被设计为具有生命周期感知能力的数据持有者。这是您的目的的开销,因为您与此层中的 View 生命周期没有任何关系。
  • 在大多数情况下,数据获取操作是一次性的(就像您的情况一样),但 LiveData 是为流设计的。
  • 它没有对结构化取消的内置支持。
  • 从架构的角度来看,android 相关的类,比如实时数据,不应该被导入到存储库层。存储库类应该作为一个简单的 Kotlin 或 java 类来实现。

  • 在您的情况下,这是特别糟糕的做法,因为 HTTP 请求不应更改存储库对象的状态。您使用 LiveData 作为一种缓存,但对此没有这样的要求,因此您应该避免这种情况。尽管如此,如果您需要在您的存储库中使用 LiveData,您应该将 MutableLiveData 作为参数传递给您的请求方法,以便您可以通过此 LiveData 发布响应或在您的请求方法中返回一个 LiveData。
    RxJava:它是选项之一。它支持一次性请求(Single)、热流(Subject)和冷流(Observable)。它以某种方式支持结构化取消(CompositeDisposable)。它有一个稳定的 API,并且已经被普遍使用多年。它还使许多不同的网络操作更容易,例如并行请求、顺序请求、数据操作、线程切换等等。
    协程:这是另一种选择,在我看来,这是最好的。虽然它的 API 不是完全稳定,但我已经在很多不同的项目中使用过它,我没有看到任何问题。它支持一次性请求(挂起函数)、热流(Channels 和 Stateflow)和冷流(Flow)。它在需要复杂数据流的项目中非常有用。它是 Kotlin 中所有运算符的内置功能。它以一种非常优雅的方式支持结构化并发。它有许多不同的运算符函数,与 RxJava 相比,它更容易实现新的运算符函数。它还具有与 ViewModel 一起使用的有用扩展函数。
    总而言之,存储库层是传入数据的网关,这是您操作数据以符合应用程序要求的第一个地方,如上所述。可以在这一层中完成的操作可以简单地列为映射传入数据、决定从何处获取数据(本地或远程源)和缓存。有很多选项可以将数据传回请求数据的类,但是 RxJava 和 Coroutines 比我上面解释的其他方法更好。在我看来,如果你对它们都不熟悉,那就把精力放在 Coroutines 上。

    关于java - MVVM with Retrofit - 如何处理 Repository 中的大量 LiveData?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66467435/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com