ViewModelProvider.Factory和ViewModelProvider.NewInstanceFactory有什么区别?

16
我目前正在将我的项目架构从MVP转换为MVVM。在进行此项工作时,我发现有些事情让我感到困惑:
iosched项目的ScheduleViewModelFactory.kt中,该工厂实现了ViewModelProvider.Factory
class ScheduleViewModelFactory(
    private val userEventRepository:DefaultSessionAndUserEventRepository
) : ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(ScheduleViewModel::class.java)) {
            return ScheduleViewModel(LoadUserSessionsByDayUseCase(userEventRepository)) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

在Sunshine项目中的DetailViewModelFactory.java文件中,工厂类继承了ViewModelProvider.NewInstanceFactory。该项目来自codelab教程。
public class DetailViewModelFactory extends ViewModelProvider.NewInstanceFactory {

    private final SunshineRepository mRepository;
    private final Date mDate;

    public DetailViewModelFactory(SunshineRepository repository, Date date) {
        this.mRepository = repository;
        this.mDate = date;
    }

    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        //noinspection unchecked
        return (T) new DetailActivityViewModel(mRepository, mDate);
    }
}

我想知道:

  1. ViewModelProvider.FactoryViewModelProvider.NewInstanceFactory有什么区别?
  2. 为什么像上面代码中提到的那样使用它们?
  3. 在什么情况下使用它们是最佳实践/场景?
2个回答

5

ViewModelProvider.Factory和ViewModelProvider.NewInstanceFactory有什么区别?

为什么要像上面提到的代码一样使用它们?

根据ViewModelProvider文档:

public class ViewModelProvider {
    /**
     * Implementations of {@code Factory} interface are responsible to instantiate ViewModels.
     */
    public interface Factory {
        @NonNull
        <T extends ViewModel> T create(@NonNull Class<T> modelClass);
    (...)


    /**
     * Simple factory, which calls empty constructor on the given class.
     */
    public static class NewInstanceFactory implements Factory {

        @SuppressWarnings("ClassNewInstance")
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            //noinspection TryWithIdenticalCatches
            try {
                return modelClass.newInstance();
            } catch (InstantiationException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Cannot create an instance of " + modelClass, e);
            }
        }
    }
    (...)
}

考虑到 geeksforgeeks 对于 newInstance() 的描述:

通常,new 运算符用于创建对象,但是如果我们想在运行时决定要创建的对象类型,则无法使用 new 运算符。在这种情况下,我们必须使用 newInstance() 方法。

我认为 NewInstanceFactoryFactory 的一种实现,当我们想要创建不同类型的 ViewModels 时可以使用它。


另一方面,在 google 的 android-architecture/todoapp 中有:

public class ViewModelFactory extends ViewModelProvider.NewInstanceFactory {
    (...)
    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        if (modelClass.isAssignableFrom(StatisticsViewModel.class)) {
            //noinspection unchecked
            return (T) new StatisticsViewModel(mApplication, mTasksRepository);
        } else if (modelClass.isAssignableFrom(TaskDetailViewModel.class)) {
            //noinspection unchecked
            return (T) new TaskDetailViewModel(mApplication, mTasksRepository);
        } else if (modelClass.isAssignableFrom(AddEditTaskViewModel.class)) {
            //noinspection unchecked
            return (T) new AddEditTaskViewModel(mApplication, mTasksRepository);
        } else if (modelClass.isAssignableFrom(TasksViewModel.class)) {
            //noinspection unchecked
            return (T) new TasksViewModel(mApplication, mTasksRepository);
        }
        throw new IllegalArgumentException("Unknown ViewModel class: " + modelClass.getName());
    }
}

他们正在使用NewInstanceFactory,但是却覆盖了create方法!据我理解,如果我们覆盖它,那么就没有区别于使用普通的Factory了。

“但是你们正在重写create方法!据我所知,如果我们重写它,和使用普通工厂没有区别”--你为什么这么说? - Sakiboy
2
因为NewInstanceFactory唯一的作用就是实现create()方法。如果Google正在使用NewInstanceFactory但又重写了create()方法,他们本来就可以一开始就使用常规的Factory - Steru

1
ViewModelProvider.Factory负责创建您的ViewModel实例。
如果您的ViewModel有依赖项并且想要测试您的ViewModel,那么您应该创建自己的ViewModelProvider.Factory,并通过ViewModel构造函数传递依赖项并为ViewModelProvider.Factory实例提供值。
什么时候使用ViewModelProvider.Factory?
如果您的ViewModel具有依赖关系,则应通过构造函数将这些依赖项传递(这是传递依赖项的最佳方式),因此您可以模拟这些依赖项并测试您的ViewModel。
什么时候不使用ViewModelProvider.Factory
如果您的ViewModel没有依赖项,则不需要创建自己的ViewModelProvider.Factory。默认实现足以为您创建ViewModel。
有关详细信息,请参阅blog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接