Как устранить ошибку dagger — строка не может быть предоставлена без конструктора @Inject или метода @Provides-annotated

#java #android #kotlin #dependency-injection #dagger-2

#java #Android #котлин #внедрение зависимостей #кинжал-2

Вопрос:

Привет, у меня есть класс PdfTicketStorage, в котором есть конструктор, который принимает 2 параметра, я добавил @Inject в конструктор, а также в MockServiceOrderModule. но я получаю сообщение об ошибке

MockAppComponent.java:48: error: [Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject constructor or an @Provides-annotated method.

полная ошибка

 /home/circleci/code/app/src/androidTest/java/com/xx/xxx/test/injection/components/MockAppComponent.java:48: error: [Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject constructor or an @Provides-annotated method.
public interface MockAppComponent extends AppComponent {
       ^
      java.lang.String is injected at
          com.xxx.xx.test.injection.modules.MockServiceOrderModule.providePdfTicketStorage(cloudStorageBucket, …)
      com.xxx.xx.printing.storage.PdfTicketStorage is injected at
          com.xxx.xx.clean.offline.OfflineHelper(…, pdfTicketStorage, …)
      com.xxx.xx.clean.offline.OfflineHelper is injected at
          com.xxx.xx.clean.offline.repository.OfflineUserApiRepository(…, offlineHelper)
      com.xxx.xx.clean.offline.repository.OfflineUserApiRepository is injected at
          com.xxx.xx.clean.florder.data.repository.flOrderRepository(offlineUserApiRepository, …)
      com.xxx.xx.clean.florder.data.repository.flOrderRepository is injected at
          com.xxx.xx.test.scenarios.BaseScenario.flOrderRepository
      com.xxx.xx.test.scenarios.BaseScenario is injected at
          com.xxx.xx.test.injection.components.MockAppComponent.inject(com.xxx.xx.test.scenarios.BaseScenario)
  The following other entry points also depend on it:
      com.xxx.xx.test.injection.components.MockAppComponent.inject(com.xxx.xx.test.scenarios.VehicleTakeoverScenario)
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.activities.MainActivity) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.BaseflOrderFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.BaseflOrderDataFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.flOrderDataFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.flOrderSummaryFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.flOrderDeallocationFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.clean.orderslist.serviceorders.view.ServiceOrderListFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.fragments.fller.florder.ServiceOrderViewFragment) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      com.xxx.xx.injection.components.ActivityComponent.inject(com.xxx.xx.clean.orderslist.serviceorders.view.ServiceOrderAdapter) [com.xxx.xx.test.injection.components.MockAppComponent → com.xxx.xx.injection.components.ActivityComponent]
      and 31 others/home/circleci/code/app/src/androidTest/java/com/xx/xxx/test/injection/components/MockAppComponent.java:48: error: [Dagger/MissingBinding] java.lang.String cannot be provided without an @Inject constructor or an @Provides-annotated method.
 

PdfTicketStorage

 @PerApp
public class PdfTicketStorage {

    private final String cloudStorageBucket;
    private final Lazy<OfflineHelper> offlineHelper;

    @Inject
    public PdfTicketStorage(String cloudStorageBucket, Lazy<OfflineHelper> offlineHelper) {
        this.cloudStorageBucket = cloudStorageBucket;
        this.offlineHelper = offlineHelper;
    }
}
 

OfflineHelper

 @PerApp
class OfflineHelper @Inject constructor(
    private val app: App,
    private val settings: Settings,
    private val pdfTicketStorage: PdfTicketStorage,
    @Named("default") private val gson: Gson
) 
 

MockServiceOrderModule

 @Module
public class MockServiceOrderModule {

      @Provides @PerApp
    PdfTicketStorage providePdfTicketStorage(String cloudStorageBucket, Lazy<OfflineHelper> offlineHelper) {
        return new PdfTicketStorage(cloudStorageBucket, offlineHelper);
    }

}
 

Не могли бы вы подсказать, что я здесь делаю не так, пожалуйста

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

спасибо R

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

1. Похоже, вы вводите строку где-то внутри MockServiceOrderModule . Либо укажите строку в модуле, либо избегайте ее введения.

2. привет, когда вы говорите, избегайте его введения? что вы имели в виду под этим, удалите Inject из ` @Inject public PdfTicketStorage(строка cloudStorageBucket, ленивый<OfflineHelper> offlineHelper) { this.cloudStorageBucket = cloudStorageBucket; this.offlineHelper = offlineHelper; }`

Ответ №1:

Ациклический граф Dagger не знает, как указать тип String , в случае String cloudStorageBucket . Есть два решения:

  1. Либо создайте другой @Provides для String . Это не рекомендуется, так как вы столкнетесь с проблемой, если потребуется другой String тип.
  2. (Рекомендуется) Отметьте @Provides в 1 с @Named("cloudStorageBucket") помощью .

Вы также можете использовать @assisted-inject , если это String будет предоставлено во время выполнения.

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

1. Привет, @Karan ты имел в виду это из 2-го рекомендуемого варианта « @Provides @PerApp PdfTicketStorage providePdfTicketStorage(@Named(«по умолчанию») Строка cloudStorageBucket, Lazy<OfflineHelper> offlineHelper) { возвращает новый PdfTicketStorage(cloudStorageBucket, offlineHelper); }«

2. Что происходит прямо сейчас, так это то, что вы просите dagger предоставить вам экземпляр String из своего графика. Если у вас есть provides, которые возвращают строку, то dagger вернет ее. Но причина, по которой хорошей идеей было бы назвать эту строку, заключается в том, что в будущем вам может потребоваться предоставить больше строковых зависимостей.

Ответ №2:

Прежде всего, когда вы уже предоставляете объект здесь, в этом модуле dagger:

 @Module
public class MockServiceOrderModule {

      @Provides @PerApp
    PdfTicketStorage providePdfTicketStorage(String cloudStorageBucket, Lazy<OfflineHelper> offlineHelper) {
        return new PdfTicketStorage(cloudStorageBucket, offlineHelper);
    }

}
 

Вам не нужно использовать внедрение конструктора в PdfTicketStorage классе. Вы можете просто ввести объект и использовать его следующим образом:

 @PerApp
public class PdfTicketStorage {

    @Inject
    public PdfTicketStorage pdfTicketStorage;
}
 

Но также вы должны убедиться, что строка также указана в модуле dagger. Не знаете, зачем вам нужно указывать строку в модуле dagger?