理解Android架构组件示例GithubBrowserSample: ViewModelModule,ViewModel参数

18

谷歌提供的GithubBrowserSample是涵盖Android Architecture Components最新范例之一。我已经审查了代码,有几个问题:

  1. 我注意到ViewModelModule包含在AppModule中。这意味着所有的viewmodels都添加到了DI图中。为什么要以这种方式做,而不是为每个Activity / Fragment单独创建一个Module,为特定的Activity / Fragment提供所需的ViewModel

  2. 在这个特定的示例中,使用GithubViewModelFactory实例化viewmodels时,是否有办法向特定的ViewModel传递参数?或者更好的解决方案是在ViewModel中创建一个setter,并通过setter设置所需的参数?


有人已经创建了这个请求:https://github.com/googlesamples/android-architecture-components/issues/148 - Vadims Savjolovs
1个回答

11
它意味着所有的视图模型都被添加到DI图中。为什么要这样做,而不是为每个Activity/Fragment单独创建一个Module?它们被添加到DI图中,但它们尚未被创建。相反,它们最终会出现在提供程序映射中,如在ViewModelFacory中看到的那样
@Inject
public GithubViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) { }

现在我们有了一个GithubViewModelFactory,它拥有一系列的提供者并且可以创建任何已绑定的ViewModel。Fragments和Activities现在只需要注入工厂并获取他们的ViewModel即可。

@Inject
ViewModelProvider.Factory viewModelFactory;

// ...later...
repoViewModel = ViewModelProviders.of(this, viewModelFactory).get(RepoViewModel.class);

关于为什么...另外你可以为每个Activity/Fragment创建一个ViewModelProvider.Factory,并在每个Module中注册实现。但这将会产生大量重复的样板代码。
在这个特定的例子中,使用GithubViewModelFactory实例化viewmodel时,是否有办法向特定的ViewModel传递参数?或者更好的解决方案是在ViewModel中创建setter方法,并通过setter设置所需的参数?
似乎所有的ViewModel都只依赖于@Singleton对象 - 这是必要的,因为它们都是从AppComponent提供的。这意味着除了其他@Singleton依赖项之外,没有其他传递“参数”的方法。
因此,正如你建议的那样,你要么必须将工厂移动到Activity/Fragment组件中,以便你可以提供较低范围的依赖项,要么使用setter方法。

在早期的dagger2版本(没有dagger.android),我使用了子组件。因此,在activity中,我可以这样做:App.get(context).appComponent.plus(MyModule("12345")).inject(this)。所以在这个模块中,我可以实例化一个带有参数ViewModelProvider.Factory("12345")的工厂,它可以为我创建带有参数的ViewModel。那么,我如何使用dagger.android注入来实现同样的功能呢? - Vadims Savjolovs
我发现了这个方法 https://github.com/Nimrodda/dagger-androidinjector/blob/master/app/src/main/java/org/codepond/daggersample/feature/FeatureModule.java#L32 或许那就是正确的方式。 - Vadims Savjolovs
请注意,Android部分仍处于“@Beta”状态。目前不支持非默认构造函数模块,因此您发布的链接似乎是一个可能的方法。 - David Medenjak
关于为什么...你可以为每个Activity / Fragment创建一个ViewModelProvider.Factory,并在每个Module中注册实现。实际上这就是我所做的,否则您可能会遇到DI图的问题,例如在您的ViewModel中提供每个片段的注入可能会导致dagger错误“inject需要@provides注释...” - Samuel Eminet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接