Нарушение циклической зависимости в Dagger
Я очень плохо знаком с кинжалом - я даже не знаю, сработает ли он для моего приложения
У меня есть страница поиска, которая возвращает последние новости о данной знаменитости.
Я написал тест, чтобы убедиться, что результаты появляются на странице, когда мы ищем популярную знаменитость.
page
имеет searchField
, что требует page
в своем конструкторе, поэтому веб-драйвер, который я использую для своих тестов, может выбрать его.
Тест страницы поиска знаменитостей
public class CelebritySearchPageTest {
@Test
public void testSearchResultsForKevinBaconVerifyHisPopularity() {
CelebritySearchPage searchPage = new CelebritySearchPage();
searchPage.searchFor("Kevin Bacon");
Assert.assertTrue(searchPage.getNumberOfResults() > 9999999, "Verify that Kevin Bacon is still relevant");
}
}
Страница поиска знаменитостей
public class CelebritySearchPage extends Page {
@Inject
@Named("search field")
TextField searchField;
public void searchFor(String text) {
searchField.setText(text);
// ...
}
public int getNumberOfResults() {
// ...
}
}
Модуль Страницы Поиска Знаменитости
@Module(injects = CelebritySearchPage.class)
public class CelebritySearchPageModule {
@Provides
@Named("search field")
public TextField provideSearchField() {
return new TextField(/* How do I get the page? */, "#searchField");
}
}
страница
public abstract class Page {
// ...
}
Текстовое поле
public class TextField {
protected Page page;
protected String selector;
public TextField(Page page, String selector) {
this.page = page;
this.selector = selector;
}
public void setText(String text) {
// ...
}
}
Проблема в том, что page
потребности searchField
, но searchField
потребности page
, Как мне преодолеть эту циклическую зависимость?
Я не могу инициализировать searchField
внутри Celebrity Search Page
1 ответ
Учти это:
CelebritySearchPage
public class CelebritySearchPage extends Page {
private final Lazy<TextField> searchField;
// always prefer constructor injection
// avoid @Named if possible, since the compiler cannot check the string
@Inject
CelebritySearchPage(@Named("search field") Lazy<TextField> searchField) {
this.searchField = searchField;
}
}
Текстовое поле
public class TextField {
protected final Lazy<Page> page;
protected final String selector;
@Inject TextField(Lazy<Page> page, String selector) {
this.page = page;
this.selector = selector;
}
/*
Lazy::get()
Return the underlying value, computing the value if necessary. All calls to the same Lazy instance will return the same result.
*/
}
Думаю, одного ленивого должно хватить.