如何在其构造函数中注入具有id参数的ViewModelFactory?

时间:2018-05-19 07:06:25

标签: android dagger android-viewmodel

我在Android中使用ViewModel和Dagger来管理依赖项。我的ViewModel将在创建时从MainActivity获取id。所以我在这里有这些代码:

活动:

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

我的工厂提供商:

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类来创建活动或片段组件。所以我应该为每个活动创建一个子组件,并为我应该编写的构建器和其他代码的音调。

是否有任何简单而更好的方法可以防止这些额外的代码,或者通过在这样的活动中调用一个新工厂来制作我的工厂更好?:

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

1 个答案:

答案 0 :(得分:0)

在我看来,从new ViewModelProviderFactory(id)调用Activity是一个更简单的解决方案。 Hovewer,我不会使用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更好的名称;)