MVVM - 如何跨多个 ViewModel 共享单个存储库 class

MVVM - How to share a single repository class across multiple ViewModels

我有多个访问单个存储库的视图模型(一个 activity 和其余片段)。

AdminActivityViewModel

AdminListUsersViewModel

AdminUserTransactionsViewModel

...还有一些

我的 AdminRepo class 有多个构造函数,因此我可以从 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 class?

我考虑过使用 .getInstance() 方法使我的 AdminRepo class 成为单例,但我收到了很多关于 Repository classes 应该如何处理的自相矛盾的帖子不是静态的或单例的,这让我对我应该做什么感到非常困惑。

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

首先你需要让你的视图模型接受外部依赖(I\d推荐看dependency injection模式)

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 以便您的存储库与 activity.

一样长

现在,如果这些视图模型具有不同的生命周期并且它们不重叠,则完全可以为它们中的每一个创建一个新实例。当你不再需要它们时,你不会想在内存中保留不必要的对象。