I am working on app that uses MVVM, Room and dagger hilt, I have implemented first part that handle server response, remote DataSource, viewmodel and all this stuff, and it's worked fine, but after I implemented the database module, I got this error when I tried to build
public abstract static class SingletonC implements BaseApplication_GeneratedInjector,
^
com.test.dummyappv3.data.database.ItemDAO is injected at
com.test.dummyappv3.di.DatabaseModule.provideDao(itemDAO)
com.test.dummyappv3.data.database.ItemDAO is injected at
com.test.dummyappv3.data.LocalDataSource(itemDAO)
com.test.dummyappv3.data.LocalDataSource is injected at
com.test.dummyappv3.data.Repository(�, localDataSource)
com.test.dummyappv3.data.Repository is injected at
com.test.dummyappv3.viewmodels.PostViewModel(repository)
com.test.dummyappv3.viewmodels.PostViewModel is injected at
com.test.dummyappv3.viewmodels.PostViewModel_HiltModules.BindsModule.binds(vm)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.test.dummyappv3.BaseApplication_HiltComponents.SingletonC ? com.test.dummyappv3.BaseApplication_HiltComponents.ActivityRetainedC ? com.test.dummyappv3.BaseApplication_HiltComponents.ViewModelC]
and I think it's related with ActivityRetainedScoped
in Repository Class
@ActivityRetainedScoped
public class Repository {
public RemoteDataSource remoteDataSource;
public LocalDataSource localDataSource;
@Inject
public Repository(RemoteDataSource remoteDataSource, LocalDataSource localDataSource) {
this.remoteDataSource = remoteDataSource;
this.localDataSource = localDataSource;
}
}
DatabaseModule
@InstallIn(SingletonComponent.class)
@Module
public class DatabaseModule {
@Singleton
@Provides
public static ItemsDatabase provideDatabase(@ApplicationContext Context context){
return Room.databaseBuilder(context,ItemsDatabase.class,"items_database")
.fallbackToDestructiveMigration()
.build();
}
@Singleton
@Provides
public static ItemDAO provideDao(ItemDAO itemDAO){
return itemDAO;
}
}
RemoteDataSource
private final PostAPIService postAPIService;
@Inject
public RemoteDataSource(PostAPIService postAPIService) {
this.postAPIService = postAPIService;
}
public Observable<PostList> getPostList(String URL) {
return postAPIService.getPostList(URL);
}
public Observable<PostList> getPostListByLabel(String URL) {
return postAPIService.getPostListByLabel(URL);
}
}
LocalDataSource
public class LocalDataSource {
private final ItemDAO itemDAO;
@Inject
public LocalDataSource(ItemDAO itemDAO) {
this.itemDAO = itemDAO;
}
public Completable insertItem(Item item){
return itemDAO.insert(item);
}
public Flowable<List<Item>> getAlItems(){
return itemDAO.getAlItems();
}
}
and finally the viewmodel
@HiltViewModel
public class PostViewModel extends ViewModel {
public static final String TAG = "PostViewModel";
private Repository repository = null;
public MutableLiveData<PostList> postListMutableLiveData = new MutableLiveData<>();
public MutableLiveData<String> finalURL = new MutableLiveData<>();
public MutableLiveData<String> token = new MutableLiveData<>();
public MutableLiveData<String> label = new MutableLiveData<>();
public MutableLiveData<Boolean> ifAnythingWrongHappened = new MutableLiveData<>();
@Inject
public PostViewModel(Repository repository) {
this.repository = repository;
}
public final LiveData<List<Item>> getAllPostsFromDB
= LiveDataReactiveStreams.fromPublisher(repository.localDataSource.getAlItems());
@SuppressLint("CheckResult")
public void getPosts() {
ifAnythingWrongHappened.setValue(false);
Log.e(TAG, finalURL.getValue());
repository.remoteDataSource.getPostList(finalURL.getValue())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<PostList>() {
@Override
public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
}
@Override
public void onNext(@io.reactivex.rxjava3.annotations.NonNull PostList postList) {
Log.e(TAG, postList.getNextPageToken());
token.setValue(postList.getNextPageToken());
postListMutableLiveData.setValue(postList);
for (int i = 0; i < postList.getItems().size(); i++) {
repository.localDataSource.insertItem(postList.getItems().get(i))
.subscribeOn(Schedulers.computation())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
}
@Override
public void onComplete() {
}
@Override
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
Log.e(TAG, "onError: "+e.getMessage() );
ifAnythingWrongHappened.setValue(true);
}
});
}
finalURL.setValue(finalURL.getValue() + "&pageToken=" + token.getValue());
}
@Override
public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) {
Log.e(TAG, e.getMessage() + e.getCause());
ifAnythingWrongHappened.setValue(true);
}
@Override
public void onComplete() {
}
});
}
I tried to delete this @ActivityRetainedScoped
and @ApplicationContext
but the same error also I tried the @ViewModelScoped
in the viewmodel
@Singleton
@Provides
public static ItemDAO provideDao(ItemDAO itemDAO){
return itemDAO;
}
This is the circular dependency. The important part of that error trace to look at is everything from the first entry (ItemDAO
) up to and excluding the second appearance of that same class. The rest of the error message is showing one use of ItemDAO
in the dependency graph, since Dagger only validates reachable dependencies.
I assume you intended to do something like this instead:
@Singleton
@Provides
public static ItemDAO provideDao(ItemsDatabase database){
return database.itemDAO();
}