ошибка: [Кинжал/Цикл зависимостей] Обнаружена ошибка цикла зависимостей после использования ActivityRetainedScoped

#java #android #android-room #dagger-2 #dagger-hilt

Вопрос:

Я работаю над приложением, которое использует MVVM, комнату и рукоятку кинжала, я реализовал первую часть, которая обрабатывает ответ сервера, удаленный источник данных, модель представления и все такое, и это работало нормально, но после того, как я внедрил модуль базы данных, я получил эту ошибку, когда пытался построить

 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]
 

и я думаю, что это связано с ActivityRetainedScoped классом в репозитории

 @ActivityRetainedScoped
public class Repository {

    public RemoteDataSource remoteDataSource;
    public LocalDataSource localDataSource;

    @Inject
    public Repository(RemoteDataSource remoteDataSource, LocalDataSource localDataSource) {
        this.remoteDataSource = remoteDataSource;
        this.localDataSource = localDataSource;
    }
}
 

Модуль базы данных

 @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;
    }
}
 

Удаленный источник данных

     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();
    }

}
 

и, наконец, модель представления

 @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()   "amp;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() {

                    }
                });
}
 

Я попытался удалить это @ActivityRetainedScoped , @ApplicationContext но та же ошибка, которую я также попытался @ViewModelScoped исправить в viewmodel

Ответ №1:

     @Singleton
    @Provides
    public static ItemDAO provideDao(ItemDAO itemDAO){
        return itemDAO;
    }
 

Это циклическая зависимость. Важная часть этой трассировки ошибок, на которую следует обратить внимание, — это все, начиная с первой записи ( ItemDAO ) и заканчивая вторым появлением того же класса и исключая его. Остальная часть сообщения об ошибке показывает одно использование ItemDAO в графике зависимостей, так как Dagger проверяет только доступные зависимости.

Я предполагаю, что вы намеревались сделать что-то подобное вместо этого:

     @Singleton
    @Provides
    public static ItemDAO provideDao(ItemsDatabase database){
        return database.itemDAO();
    }
 

Комментарии:

1. О! это глупая ошибка, я видел ее на уроке, но я изменил ее с базы данных на itemDao, я не знал, что это будет по-другому, в любом случае спасибо за это уведомление, я не понял, чтобы читать ошибки кинжала 🙂

2. Что я могу сделать без StackOverflow?? У меня точно такая же ошибка. Спасибо @DrMido за спасение дня.