В настоящее время я трансформирую архитектуру своего проекта с 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);
}
}
Я бы хотел знать:
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.
потому что единственное, что делает NewInstanceFactory, это реализация метода create(). Если Google использует NewInstanceFactory, но переопределяет метод create(), в первую очередь они могли использовать обычный Factory.
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 за вас.
Пожалуйста, просмотрите этот блог для получения подробной информации.
«но переопределяют метод create! Насколько я понимаю, если мы переопределим его, нет никакой разницы от использования обычного Factory» - почему вы так говорите?