【问题标题】:MVVM - How to share a single repository class across multiple ViewModelsMVVM - 如何跨多个 ViewModel 共享单个存储库类
【发布时间】:2021-06-22 07:26:09
【问题描述】:

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

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 类?

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

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

【问题讨论】:

  • 为什么您认为在每个 VM 中创建一个新实例不好?没有什么不妥。如果您没有理由使用 Singleton,则不要创建一个,如果您确实有理由使用它,请继续。对此没有真正正确的答案,仅取决于具体情况。话虽这么说,如果您需要许多不同的回调,那么您可能可以将该回购进一步分解为单独的回购,我也不会将 Application 传递给它们,传递您需要的信息,这样您就不会依赖 Android System
  • 因为创建不必要的对象不好?在课堂上,他们教你应该始终减少对象创建的数量。我觉得您可以重用 AdminRepo 类,而不是每次都创建一个新类。
  • 不必要的工作也会造成不必要的复杂性,这不像您在几秒钟内创建数百个实例。处理完它们后,它们会收集垃圾
  • 我已经为UserLoginAdmin 实体创建了单独的存储库类。如果我要拆分Admin,我将不得不再创建5 个额外的存储库类,AdminListUsersRepoAdminListTransactionsRepo````, etc. Also why is having a dependency on the Application``` 不好?我可以在应用程序的生命周期内只拥有一个 SharedPreferences 和 Retrofit 实例,然后只检索这些实例而不是创建一个新实例。

标签: android repository-pattern android-viewmodel android-mvvm


【解决方案1】:

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

首先您需要让您的视图模型接受外部依赖项(我建议您查看dependency injection 模式)

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

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

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

@Singleton
class MyRepository { ...

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 2018-02-22
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多