15

我目前正在将我的项目架构从 MVP 转换为 MVVM。当我研究它时,我发现有些事情让我感到困惑:

ioschedScheduleViewModelFactory.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")
    }
}

DetailViewModelFactory.java来自codelab的 Sunshine 项目中,工厂扩展了ViewModelProvider.NewInstanceFactory:

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. 使用它们的最佳实践/场景是什么?
4

2 回答 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() 方法。

我假设它NewInstanceFactory是 的一个实现,Factory当我们想要创建不同类型的 ViewModel 时可以使用它。


另一方面,在 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.

于 2018-11-13T14:00:19.657 回答
0

ViewModelProvider.Factory 负责创建您的 ViewModel 实例。

如果您的 ViewModel 具有依赖项并且您想测试您的 ViewModel,那么您应该创建自己的 ViewModelProvider.Factory 并通过 ViewModel 构造函数传递依赖项,并为 ViewModelProvider.Factory 实例赋值。

何时使用 ViewModelProvider.Factory?

如果您的 ViewModel 有依赖项,那么您应该通过构造函数传递此依赖项(这是传递依赖项的最佳方式),因此您可以模拟该依赖项并测试您的 ViewModel。

何时不使用 ViewModelProvider.Factory

如果您的 ViewModel 没有依赖项,那么您将不需要创建自己的 ViewModelProvider.Factory。默认实现足以为您创建 ViewModel。

请通过此博客了解详细信息。

于 2020-12-03T07:50:02.530 回答