【发布时间】:2019-09-16 10:13:47
【问题描述】:
我刚开始使用 Dagger 框架进行依赖注入,所以我可能遗漏了一些琐碎的东西,但我花了 2 天多的时间来复习代码和教程。
所以,我正在尝试为我的ViewModels 使用 dagger 依赖注入,我发现我可以使用我已经实现的称为多重绑定的功能来做到这一点。我有一个AppComponent 和一个ActivitySubComponent。 AppComponent 安装了 ViewModelFactoryModule 其中 @Binds 和 ViewModelProvider.Factory,我希望在应用程序中使用这个 Module,因为我认为它应该独立于 Activity 生命周期。在我的ActivitySubComponent 中,我有一个ViewModelsModule,其中@Binds 一个ViewModel。
现在,据我了解,我已将 ActivitySubComponent 包含在 ViewModelFactoryModule 中,这会将子组件添加到 AppComponent。
编辑:
现在,当我制作/构建项目时,我收到以下错误。抱歉,原来的错误是:
error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.mobile.presentation.viewmodels.build.ViewModelFactory(creators)
com.mobile.presentation.viewmodels.build.ViewModelFactory is provided at
com.mobile.app.AppComponent.obtainViewModelsFactory()
在AppComponent.javaMap<Class<? extends ViewModel>, Provider<ViewModel>> obtainMap();添加如下方法后出现如下错误。
error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is provided at
com.mobile.app.AppComponent.obtainMap()
It is also requested at:
com.mobile.presentation.viewmodels.build.ViewModelFactory(creators)
The following other entry points also depend on it:
com.mobile.app.AppComponent.obtainViewModelsFactory()
jibber jabber 够了,下面是相关代码:
AppComponent.java
@AppScope
@Component(
modules = {
AppModule.class,
ViewModelFactoryModule.class
})
public interface AppComponent {
App obtainApp();
ViewModelFactory obtainViewModelsFactory();
// I tried with adding the following line, out of sheer annoyance.
// Map<Class<? extends ViewModel>, Provider<ViewModel>> obtainMap();
}
ViewModelFactoryModule.java
@Module(subcomponents = ActivitySubComponent.class)
public abstract class ViewModelFactoryModule {
@AppScope
@Binds
public abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory viewModelFactory);
}
ViewModelsFactory.java
@AppScope
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass)
{
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
ActivitySubComponent.java
// I have a separate module for my `LiveData`.
@ActivityScope
@Subcomponent(
modules = {
ActivityModule.class,
ViewModelsModule.class,
SplashLiveDataModule.class
}
)
public interface ActivitySubComponent {
Activity obtainActivity();
LiveData<InitialAPIResponse> obtainLiveInitialApiResponse();
LiveData<InitialSplashApiStatus> obtainLiveInitialSplashApiStatus();
@Subcomponent.Builder
interface Builder {
ActivitySubComponent build();
Builder setActivityModule(ActivityModule activityModule);
}
}
ViewModelsModule.java
@Module
public abstract class ViewModelsModule {
@ActivityScope
@Binds
@IntoMap
@ViewModelKey(SplashViewModel.class)
public abstract ViewModel provideVideoListViewModel(SplashViewModel viewModel);
}
现在,我从中了解到AppComponent 不能直接访问ActivitySubComponent,但它应该能够访问SubComponent,因为@Subcomponent 是作为组件的内部类生成的(也许我遗漏了一些东西),而且我认为 ViewModels 不应该绑定到应用程序的组件(我这样说是因为如果我将 ViewModelsModule 也移动到 AppComponent 我可以运行代码并且一切正常对),我的逻辑方法错了吗?
匕首依赖:
implementation 'com.google.dagger:dagger:2.22'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22'
【问题讨论】:
-
请在此处发布 ViewModelFactory 代码。
-
@ArslanShoukat 添加。
-
按照 google 的 GithubBrowserSample 示例:github.com/googlesamples/android-architecture-components/tree/… 这是一个非常简单且可扩展的设置
-
我没有将回调传递/注入到
UseCase,而是从UseCases 公开/返回可观察对象。这是一个包含用例、存储库模式和协程的基本示例:github.com/googlesamples/android-architecture/tree/usecases -
这是在不使用 dagger-android 的情况下执行组件和子组件的样板方式(因为您想深入研究 dagger)stackoverflow.com/a/29943394/2235972 这是使用 dagger 和 dagger-android 设置 di 的简单方法 @ 987654324@
标签: java android viewmodel dagger-2 android-viewmodel