Как предоставить пользовательские зависимости для инжектора конструктора с помощью Dagger - PullRequest
0 голосов
/ 17 октября 2018

У меня есть NetworkDataSource, который я хочу ввести.Я хочу использовать инъекцию конструктора , потому что я владелец этого класса:

 public class NetworkDataSource {

    @Inject
    public NetworkDataSource(String url, String method) {
        this.url = url;
        this.method = method;
    }
 }

Дело в том, что аргументы этого конструктора (которые являются зависимостями) извлекаются изService в качестве дополнения при срабатывании BroadcastIntent.Итак, мой вопрос: как я могу предоставить эти аргументы, извлеченные из Service для моего NetworkDataSource инжектора конструктора?

Service выглядит так:

public class Service extends IntentService {

   // I would like to inject NetworkDataSource
   //@Inject
   //NetworkDataSource netWorkDataSource;

   public String url;
   public String method;

   @Override
   protected void onHandleIntent(Intent workIntent) {
     url = workIntent.getStringExtra("url");
     method = workIntent.getStringExtra("method");
   }

   ............
   ............

   networkDataSource.myMethod();
}

Спасибо.

Ответы [ 3 ]

0 голосов
/ 17 октября 2018

Давайте сделаем это шаг за шагом.(Весь код будет в kotlin)

Прежде всего, у вас есть

class NetworkDataSource(val url: String, val method: String)

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

@Module
class NetworkModule {
    @Provides
    fun dataSource(@Named("url") url: String, 
                   @Named("method") method: String): NetworkDataSource {
        return NetworkDataSource(url, method)
    }
}

после этого вам нужен кинжал компонент

@Component(modules = [NetworkModule::class])
interface NetworkComponent {
    fun inject(service: Service)
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun url(@Named("url") url: String): Builder
        @BindsInstance
        fun method(@Named("method") method: String): Builder
        fun build(): NetworkComponent
    }
}

Теперь вы можете ввести его внутрь Service

class Service : IntentService {
    @Inject
    lateinit var netWorkDataSource: NetworkDataSource
    override protected fun onHandleIntent(workIntent: Intent) {
        val url = workIntent.getStringExtra("url")
        val method = workIntent.getStringExtra("method")
        DaggerNetworkComponent.builder()
            .url(url)
            .method(method)
            .build()
            .inject(this)
    }
}

Вот и все.

0 голосов
/ 17 октября 2018

Это сложный вопрос, потому что вы думаете, что Dagger в первую очередь решает проблему, заключающуюся в том, что теперь вам больше не нужно вводить классы «Фабрика» для переконфигурирования поведения.

Однако вам все равно нужноиспользуйте классы "Фабрика" для создания объектов с динамическими аргументами конструктора , полученными во время выполнения.

Итак:

 public class NetworkDataSource {

    @Inject
    public NetworkDataSource(String url, String method) {
        this.url = url;
        this.method = method;
    }
 }

будет

@Singleton
public class NetworkDataSourceFactory {
    private final OkHttpClient okHttpClient;
    private final Gson gson;

    @Inject
    public NetworkDataSourceFactory(OkHttpClient okHttpClient, Gson gson) {
        this.okHttpClient = okHttpClient;
        this.gson = gson;
    }

    public NetworkDataSource create(String url, String method) {
        return new NetworkDataSource(okHttpClient, gson, url, method);
    }
}

Тогда теперь вы можете ввести NetworkDataSourceFactory и создать NetworkDataSource, когда получите аргументы:

@Inject NetworkDataSourceFactory factory;

....
    networkDataSource = factory.create(url, method);

Предположительно, вы можете использовать AutoFactory, чтобы помочь с созданием фабрики, но у меня нетЯ еще не использовал его, все, что я знаю, это то, что он существует для этого конкретного варианта использования.

РЕДАКТИРОВАТЬ: вы также можете проверить https://github.com/square/AssistedInject, чтобы помочь с этой проблемой.

0 голосов
/ 17 октября 2018

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

...