Как передать параметры в модуль кинжала из действия или фрагмента во время выполнения - PullRequest
0 голосов
/ 28 декабря 2018

Мои спецификации программного обеспечения следующие:

Android Studio 3.4
dagger-android 2.16

У меня есть следующий класс, который передает MapboxGeocoder, который будет выполнять и возвращать ответ.

class GeocodingImp(private val mapboxGeocoder: MapboxGeocoder) : Geocoding {

    override fun getCoordinates(address: String, criteria: String): AddressCoordinate {
        val response = mapboxGeocoder.execute()

        return if(response.isSuccess && !response.body().features.isEmpty()) {
            AddressCoordinate(
                response.body().features[0].latitude,
                response.body().features[0].longitude)
        }
        else {
            AddressCoordinate(0.0, 0.0)
        }
    }
}

Однако,MapboxGeocoder генерируется в модуле кинжала во время компиляции.Поэтому я должен указать строку для адреса и TYPE_ADDRESS.

@Reusable
@Named("address")
@Provides
fun provideAddress(): String = "the address to get coordinates from"

@Reusable
@Provides
@Named("geocoder_criteria")
fun provideGeocoderCriteria(): String = GeocoderCriteria.TYPE_ADDRESS

@Reusable
@Provides
fun provideMapboxGeocoder(@Named("address") address: String, @Named("geocoder_criteria") geocoderCriteria: String): MapboxGeocoder =
    MapboxGeocoder.Builder()
        .setAccessToken("api token")
        .setLocation(address)
        .setType(geocoderCriteria)
        .build()

@Reusable
@Provides
fun provideGeocoding(mapboxGeocoder: MapboxGeocoder): Geocoding =
    GeocodingImp(mapboxGeocoder)

мой component класс:

interface TMDispatchMobileUIComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: TMDispatchMobileUIApplication): Builder

        fun build(): TMDispatchMobileUIComponent
    }

    fun inject(application: TMDispatchMobileUIApplication)
}

В основной деятельности я бы использовал это какпользователь может ввести другой адрес или изменить критерии на другое.Но так как модуль скомпилирован, я не могу передать им какие-либо параметры во время выполнения:

presenter.getAddressCoordinates("this should be the actual address", GeocoderCriteria.TYPE_ADDRESS)

Для инъекции в Activity я использую следующее:

AndroidInjection.inject(this)

Есть ли какое-либо решение дляэта проблема?

Ответы [ 4 ]

0 голосов
/ 14 января 2019

Проблема, с которой вы можете столкнуться, может быть решена с использованием подхода «Assisted инъекция».

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

К сожалению, Dagger 2 не имеет этой функции из коробки.Тем не менее, Джейк Уортон работает над отдельной библиотекой , которую можно прикрепить к Dagger.Более того, вы можете найти более подробную информацию в его выступлении на Droidcon London 2018, где он посвятил целый раздел разговоров по этому вопросу: https://jakewharton.com/helping-dagger-help-you/

0 голосов
/ 30 декабря 2018

При желании вы можете воссоздать весь ваш компонент во время выполнения, где вы затем передадите параметры своему модулю в качестве параметра конструктора.Что-то вроде:

fun changeAddress(address: String) {
    val component = DaggerAppComponent.builder() //Assign this to wherever we want to keep a handle on the component
            .geoModule(GeoModule(address))
            .build()
    component.inject(this) //To reinject dependencies
}

И ваш модуль будет выглядеть так:

@Module
class AppModule(private val address: String) {...}

Этот метод может быть расточительным, если вы создаете много разных объектов в своем компоненте.

0 голосов
/ 12 января 2019

Другой подход, по сравнению с уже приведенными ответами, состоит в том, чтобы получить «Фабрику» с помощью внедрения зависимости кинжала под названием GeoModelFactory, которая может создавать для вас новые экземпляры GeoModel.

Вы можете передать адрес и тип фабрике, которая создает ваш экземпляр.Для оптимизации вы можете либо сохранить ссылки для всех различных адресов / типов, которые уже были запрошены (может привести к утечке памяти, если есть много разных, если старые не удаляются), или этого также может быть достаточно, если вы храните толькопоследний экземпляр и в других частях кода просто попросить фабрику предоставить вам GeoModel, который был создан последним.

0 голосов
/ 29 декабря 2018

MapboxGeocoder создаются динамически во время выполнения, в этом случае кинжал не сильно помогает, так как его цель - помочь вам построить граф объектов во время компиляции, как вы пишете код вручную.

Так что, на мой взгляд, вы должны создать MapboxGeocoder внутри getCoordinates().

...