Нарушение циклической зависимости в 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.
*/
}

Думаю, одного ленивого должно хватить.

Другие вопросы по тегам