首页 > 解决方案 > MVVM - 如何跨多个 ViewModel 共享单个存储库类

问题描述

我有多个视图模型可以访问单个存储库(一个活动和其余片段)。

AdminActivityViewModel

AdminListUsersViewModel

AdminUserTransactionsViewModel

......还有更多

我的AdminRepo类有多个构造函数,因此我可以从 ViewModel 传递回调方法

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

        SharedPrefManager sharedPref = SharedPrefManager.getInstance(application);
        AuthHeader authHeader = new AuthHeader(
                sharedPref.getIdToken(),
                sharedPref.getIdClient(),
                sharedPref.getUserEmail()
        );
        client.setAuthHeader(authHeader);
    }
 public AdminRepo(Application application, AdminListUsersCallback callback) {
        //Exact same code in constructor as above ^
 }
 public AdminRepo(Application application, AdminUserTransactionsCallback callback) {
        //Exact same code in constructor as above ^
 }

在每一个中,ViewModels我都在创建一个实例AdminRepo(这可能是一个不好的做法),但我不知道如何改进它。

public class AdminActivityViewModel extends AndroidViewModel implements AdminActivityCallback

   public AdminActivityViewModel(@NonNull Application application) {
        super(application);
        repo = new AdminRepo(application, this);
}

如何设计我的AdminRepo和 ViewModel 以便它们共享一个存储库,而无需AdminRepo每次都创建昂贵的类?

我考虑AdminRepo过用一种方法让我的类成为单例.getInstance(),但是我收到了很多关于存储库类不应该是静态或单例的自相矛盾的帖子,这让我对我应该做什么感到非常困惑。

https://stackoverflow.com/a/7464235/11110509

标签: androidrepository-patternandroid-viewmodelandroid-mvvm

解决方案


如果所有视图模型同时存在并且存储库不保留任何状态,您可以共享相同的存储库实例并为每个视图模型提供该实例。然而,这里没有魔法的地方——如果你创建了一个存储库的实例,你必须保留对它的引用,这样你就可以将相同的对象传递给其他视图模型。

首先你需要让你的视图模型接受外部依赖(我建议查看依赖注入模式)

YourViewModel( /* other dependencies ..., */ AdminRepo adminRepo) 

一旦你有了它,你需要创建一个视图模型工厂。这篇文章很好地描述了它,但长话短说:实现ViewModelProvider.Factory将保留您的存储库实例并使用它ViewModelProvider来获取视图模型的实例。

通过此设置,您将控制您创建的实例以及如何创建其他视图模型。这可以通过使用依赖注入框架(Koin、dagger、hilt)实现自动化。如果您使用 Dagger 或Hilt(由 Google 推荐),那么您可以通过提供适当的注释将您的对象生命周期留在框架手中。让我们试试这个例子:

@Singleton
class MyRepository { ...

@HiltViewModel
class MyViewModel {
   MyRepository repo;
   @Inject MyViewModel(MyRepository repo) { ...
   ...

此代码将使您的存储库成为与您的应用程序生命周期相关联的单例。通常你不想这样做,因为即使你移动到不需要它的屏幕,对象也会存在于内存中。但是您可以使用@ActivityScoped这样您的存储库就可以在活动中存活。

现在,如果这些视图模型具有不同的生命周期并且它们不重叠,那么为它们中的每一个创建一个新实例就完全没问题了。当您不再需要它们时,您不希望将不必要的对象保留在内存中。


推荐阅读