我目前正在研究Android应用程序中Dagger2
的使用。
implementation 'com.google.dagger:dagger:2.21'
annotationProcessor 'com.google.dagger:dagger-compiler:2.21'
implementation 'com.google.dagger:dagger-android:2.21'
implementation 'com.google.dagger:dagger-android-support:2.21'
annotationProcessor 'com.google.dagger:dagger-android-processor:2.21'
我设法@Inject
的ViewModel及其相关的存储库
具有以下代码:-
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
@Singleton
public class DaggerViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public DaggerViewModelFactory(final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(final 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 (final Exception e) {
throw new RuntimeException(e);
}
}
}
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(final DaggerViewModelFactory factory);
@Binds
@IntoMap
@ViewModelKey(StilettoViewModel.class)
abstract ViewModel provideStilettoViewModel(final StilettoViewModel stilettoViewModel);
}
但是我的某些ViewModel是androidx.lifecycle.AndroidViewModel
。
我创建了这个ViewModelFactory:-
import android.app.Application;
import java.util.Map;
import javax.inject.Provider;
import javax.inject.Singleton;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
@Singleton
public class DaggerAndroidViewModelFactory extends ViewModelProvider.AndroidViewModelFactory {
private final Application application;
private Map<Class<? extends AndroidViewModel>, Provider<AndroidViewModel>> creators;
/**
* Creates a {@code AndroidViewModelFactory}
*
* @param application an application to pass in {@link AndroidViewModel}
*/
public DaggerAndroidViewModelFactory(@NonNull final Application application) {
super(application);
this.application = application;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull final Class<T> modelClass) {
return super.create(modelClass);
}
}
和此Dagger模块
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.ViewModelProvider;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.AndroidViewModelFactory bindAndroidViewModelFactory(final DaggerAndroidViewModelFactory factory);
@Binds
@IntoMap
@ViewModelKey(MyAndroidViewModel.class)
abstract AndroidViewModel provideArticlesViewModel(final ArticlesViewModel articlesViewModel);
}
当我收到此错误时,将不会构建此代码
error: [Dagger/MissingBinding] MyAndroidViewModel cannot be provided without an @Inject constructor or an @Provides-annotated method.
是否可以用Dagger2注入androidx.lifecycle.AndroidViewModel
?
我的实现哪里出错了?
答案 0 :(得分:2)
如果您有一个@Module
和@Provides
的{{1}}(或者您使用Application
+ @BindsInstance
,说实话两个都可以):
@Component.Builder
和
@Module
public class AppModule {
private final Application app;
public AppModule(Application app) {
this.app = app;
}
@Provides
Application app() { return app; }
}
然后立即代替使用AndroidViewModel:
@Component(modules={AppModule.class, ...})
@Singleton
public interface AppComponent {
}
您可以将常规ViewModel与public class MyViewModel extends AndroidViewModel {
public MyViewModel(Application app) {
...
}
}
构造函数一起使用:
@Inject
您将可以通过public class MyViewModel extends ViewModel {
@Inject
MyViewModel(Application app) {
...
}
}
像其他常规ViewModel类一样使用它。