Как сделать ViewModelFactory с параметром id в его конструкторе инъекционным? - PullRequest
0 голосов
/ 19 мая 2018

Я использую ViewModel в Android с Dagger для управления зависимостями.Моя ViewModel будет получать идентификатор из MainActivity при создании.Итак, у меня есть следующие коды:

В Activity:

@inject ViewModelProviderFactory mViewModelFactory;
ViewModelProviders.of(this, mViewModelFactory).get(MyViewModel.class);

Поставщик My Factory:

public class ViewModelProviderFactory implements ViewModelProvider.Factory {

    private int id;

    @inject
    public ViewModelProviderFactory(int id) {
        this.id = id;
    }

    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        return new MyViewModel(id);
    }    
}

Для работы мне нужно добавить параметр в мой модуль:

@Module
public class MainActivityModule {
    int id;
    public MainActivityModule(int id){ 
        this.id = id;
    }
    @Provides
    ViewModelProvider.Factory mainViewModelProvider() {
        return new ViewModelProviderFactory<>(id);
    }
}

Или я могу сделать это непосредственно в компоненте и сделать его абстрактным.В новом Dagger я могу использовать класс Dagger для создания компонента деятельности или фрагмента.Поэтому я должен создать подкомпонент для каждого действия и Builder и тонов других кодов, которые я должен написать.

Есть ли какой-нибудь простой и лучший способ предотвратить эти дополнительные коды, или лучше, если бы я создал свой Factory, вызвав простоновый завод в деятельности, как это?:

ViewModelProviders.of(this, new ViewModelProviderFactory(id)).get(MyViewModel.class);

1 Ответ

0 голосов
/ 21 мая 2018

На мой взгляд, звонить new ViewModelProviderFactory(id) из Activity - гораздо более простое решение.Однако я бы не использовал конструктор напрямую из Activity.Вместо этого я бы создал фабрику (да, фабрику фабрики ...), которую я бы вставил в Activity.

Вот пример:

class FactoryOfFactory {

    @Inject
    FactoryOfFactory() {}

    ViewModelProvider.Factory create(int id) {
        // ViewModelProviderFactory can now by just an anonymous class
        return new ViewModelProvider.Factory() {
            @Override
            public <T extends ViewModel> T create(Class<T> modelClass) {
                return (T) new MyViewModel(id);
            }
        };
    }
}

Ииспользование:

class ClientActivity extends AppCompatActivity {

    @Inject
    FactoryOfFactory factoryOfFactory;

    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final int id = 123;
        ViewModelProviders.of(this, factoryOfFactory.create(id)).get(MyViewModel.class);
    }
}

Этот метод также имеет следующее решение: если MyViewModel нужны другие зависимости (которые не предоставляются Activity), мы можем очень легко добавить их (без изменения Activity):

class MyViewModel extends ViewModel {
    MyViewModel(int id, AnotherDependency anotherDependency) { }
}

class FactoryOfFactory {

    private final AnotherDependency anotherDependency; // added

    @Inject
    FactoryOfFactory(final AnotherDependency anotherDependency) {  // modified
        this.anotherDependency = anotherDependency; // added
    }

    ViewModelProvider.Factory create(int id) {
        // ViewModelProviderFactory can now by just an anonymous class
        return new ViewModelProvider.Factory() {
            @Override
            public <T extends ViewModel> T create(Class<T> modelClass) {
                return (T) new MyViewModel(id, anotherDependency);  // modified
            }
        };
    }
}

И, конечно же, я считаю, что существуют имена, которые лучше FactoryOfFactory;)

...