В чем разница между ViewModelProvider.Factory и ViewModelProvider.NewInstanceFactory?

В настоящее время я трансформирую архитектуру своего проекта с MVP на MVVM. Когда я работаю над этим, я обнаруживаю, что меня что-то смутило:

В ScheduleViewModelFactory.kt проекта iosched фабрика реализует 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 проекта Sunshine от Codelab фабрика расширяет 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.Factory и ViewModelProvider.NewInstanceFactory?
  2. Почему они используются как коды, упомянутые выше?
  3. Каков наилучший метод / сценарий использования каждого из них?
15
0
3 027
2

Ответы 2

What are the differences between ViewModelProvider.Factory and ViewModelProvider.NewInstanceFactory?

Why they are being used like the codes mentioned above?

На основе документации 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);
            }
        }
    }
    (...)
}

и принимая во внимание выродки описание newInstance():

In general, new operator is used to create objects, but if we want to decide type of object to be created at runtime, there is no way we can use new operator. In this case, we have to use newInstance() method.

Я предполагаю, что NewInstanceFactory - это реализация Factory, которую можно использовать, когда мы хотим создавать модели представления разных типов.


С другой стороны, в Google Android-архитектура / 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! Насколько я понимаю, если мы переопределим его, нет никакой разницы от использования обычного Factory» - почему вы так говорите?

Sakiboy 25.09.2019 16:24

потому что единственное, что делает NewInstanceFactory, это реализация метода create(). Если Google использует NewInstanceFactory, но переопределяет метод create(), в первую очередь они могли использовать обычный Factory.

Steru 28.10.2019 14:08

ViewModelProvider.Factory is responsible to create your instance of ViewModel.

Если ваша ViewModel имеет зависимости и вы хотите протестировать свою ViewModel, вам следует создать свой собственный ViewModelProvider.Factory и передать зависимость через конструктор ViewModel и присвоить значение экземпляру ViewModelProvider.Factory.

When to use ViewModelProvider.Factory?

Если ваша ViewModel имеет зависимости, вы должны передать эти зависимости через конструктор (это лучший способ передать ваши зависимости), чтобы вы могли имитировать эти зависимости и протестировать свою ViewModel.

When not to use ViewModelProvider.Factory

Если ваша ViewModel не имеет зависимостей, вам не потребуется создавать собственную ViewModelProvider.Factory. Реализации по умолчанию достаточно, чтобы создать ViewModel за вас.

Пожалуйста, просмотрите этот блог для получения подробной информации.

Другие вопросы по теме