Как Аюш описано в комментариях:
Вам нужен LoginResponseListener для создания LoginRequest и вам нужен LoginRequest для создания LoginResponseListener. Итак, вы получаете ошибку.
Когда вы создаете LoginRequest в LoginRequestImp (loginUser, loginPresenter), loginPresenter является параметром для конструктора типа LoginResponseListener. Вы должны попытаться устранить эту зависимость. Может быть, вы можете установить слушателя позже от докладчика
В вашем ответе между этими комментариями:
LoginRequest был создан в provideLoginRequest
Но вот что происходит:
- Ваш LoginFragment пытается внедрить LoginPresenter.
- Перед тем, как вводить LoginPresenter, вам нужно создать LoginRequest.
- Перед созданием запроса LoginRequest вам необходимы LoginUser и LoginRequestListener.
- Прежде чем создавать LoginRequestListener (который вы реализовали как LoginPresenterImpl), вам необходимо LoginRequest.
- Вы находитесь в процессе создания LoginRequest, поэтому Dagger сдается и правильно сообщает циклическую ссылку.
Повторим: даже если вы правильно настроили привязки с помощью интерфейсов, Dagger не может создать ни один из них, потому что для вызова одного конструктора он должен создать другой. С Dagger это не проблема: если конструктор класса A принимает экземпляр B, а конструктор класса B - A, вы не можете создать ни один из них вручную, при соблюдении параметров их конструктора.
Как и предполагал Аюш, у LoginRequest нет возможности ввести LoginResponseListener. Вместо этого создайте метод, подобный setLoginResponseListener
, который может вызывать LoginPresenterImp. Я также рекомендую этот подход, отчасти потому, что @ Reusable имеет более слабую семантику, чем вы хотите : вы хотите быть абсолютно уверены, что экземпляр LoginPresenterImp, который действует как ваш LoginPresenter, является тем же экземпляром, который действует как LoginResponseListener.
В качестве альтернативы вы можете ввести Provider<LoginPresenter>
вместо LoginResponseListener
и изменить LoginRequestImp, чтобы также принимать поставщика. (Вы также можете добавить Provider<LoginResponseListener>
, но если вы хотите, чтобы LoginResponseListener был таким же, как ваш экземпляр LoginPresenter, вам не следует явно вызывать конструктор LoginPresenterImp. Вы бы хотели переключиться на @Binds
в идеале или на по крайней мере, ваш @Provides
метод вместо этого вводит LoginPresenter.) Вам разрешено внедрять провайдера, потому что a Provider<T>
автоматически связывается с каждым классом <T>
, который Даггер знает, как предоставить , и это решает вашу проблему, потому что Dagger может передать Provider<T>
, не пытаясь создать T
. Технически это будет работать, даже если вы оставите свои привязки как @Reusable
, но в многопоточной среде @Reusable
не гарантирует, что вы всегда получите тот же экземпляр LoginRequestListener, что и LoginPresenter, или что вы получите новый LoginPresenter для каждого LoginFragment. Если вы хотите это гарантировать, вы можете посмотреть пользовательских областей .