From a3c35f3a0335ea8f663bfc4c6eb173ab4e5f356e Mon Sep 17 00:00:00 2001 From: Florina Muntenescu Date: Tue, 2 Apr 2019 17:53:51 +0100 Subject: [PATCH] Trying to inject dependencies from dynamic feature modules --- .../plaidapp/core/dagger/DataSourcesModule.kt | 19 ++++--- .../SearchDataSourceFactoriesRegistry.kt | 56 +++++++++++++++++++ ...egistry.kt => SearchDataSourcesFactory.kt} | 2 +- .../core/interfaces/SearchFactoryProvider.kt | 22 ++++++++ .../dagger/DesignerNewsSearchComponent.kt | 24 ++++++++ .../plaidapp/designernews/dagger/Injector.kt | 6 ++ .../designernews/dagger/SearchDataModule.kt | 38 +++++++++++++ .../domain/search}/DesignerNewsDataSource.kt | 2 +- .../DesignerNewsSearchDataSourceFactory.kt | 5 +- .../DesignerNewsSearchFactoryProvider.kt | 37 ++++++++++++ .../domain/search}/DribbbleDataSource.kt | 2 +- .../DribbbleSearchDataSourceFactory.kt | 5 +- .../plaidapp/search/domain/SearchUseCase.kt | 6 +- .../io/plaidapp/search/ui/SearchViewModel.kt | 6 +- .../search/ui/SearchViewModelFactory.kt | 6 +- 15 files changed, 210 insertions(+), 26 deletions(-) create mode 100644 core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactoriesRegistry.kt rename core/src/main/java/io/plaidapp/core/interfaces/{SearchDataSourcesRegistry.kt => SearchDataSourcesFactory.kt} (89%) create mode 100644 core/src/main/java/io/plaidapp/core/interfaces/SearchFactoryProvider.kt create mode 100644 designernews/src/main/java/io/plaidapp/designernews/dagger/DesignerNewsSearchComponent.kt create mode 100644 designernews/src/main/java/io/plaidapp/designernews/dagger/SearchDataModule.kt rename {core/src/main/java/io/plaidapp/core/interfaces/designernews => designernews/src/main/java/io/plaidapp/designernews/domain/search}/DesignerNewsDataSource.kt (96%) rename {core/src/main/java/io/plaidapp/core/interfaces/designernews => designernews/src/main/java/io/plaidapp/designernews/domain/search}/DesignerNewsSearchDataSourceFactory.kt (89%) create mode 100644 designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchFactoryProvider.kt rename {core/src/main/java/io/plaidapp/core/interfaces/dribbble => dribbble/src/main/java/io/plaidapp/dribbble/domain/search}/DribbbleDataSource.kt (96%) rename {core/src/main/java/io/plaidapp/core/interfaces/dribbble => dribbble/src/main/java/io/plaidapp/dribbble/domain/search}/DribbbleSearchDataSourceFactory.kt (89%) diff --git a/core/src/main/java/io/plaidapp/core/dagger/DataSourcesModule.kt b/core/src/main/java/io/plaidapp/core/dagger/DataSourcesModule.kt index b36fc49d3..130d20481 100644 --- a/core/src/main/java/io/plaidapp/core/dagger/DataSourcesModule.kt +++ b/core/src/main/java/io/plaidapp/core/dagger/DataSourcesModule.kt @@ -18,21 +18,24 @@ package io.plaidapp.core.dagger import dagger.Module import dagger.Provides +import io.plaidapp.core.interfaces.SearchDataSourceFactoriesRegistry import io.plaidapp.core.interfaces.SearchDataSourceFactory -import io.plaidapp.core.interfaces.SearchDataSourcesRegistry -import io.plaidapp.core.interfaces.designernews.DesignerNewsSearchDataSourceFactory -import io.plaidapp.core.interfaces.dribbble.DribbbleSearchDataSourceFactory +import io.plaidapp.core.interfaces.SearchDataSourcesFactory @Module class DataSourcesModule { + @Provides + fun searchDataSourceFactoriesRegistry(): SearchDataSourceFactoriesRegistry { + return SearchDataSourceFactoriesRegistry() + } + @Provides fun searchDataSourcesRegistry( - dnDataSourceFactory: DesignerNewsSearchDataSourceFactory, - dribbbleSourceFactory: DribbbleSearchDataSourceFactory - ): SearchDataSourcesRegistry { + factoriesRegistry: SearchDataSourceFactoriesRegistry + ): SearchDataSourcesFactory { val factories: List = - listOf(dnDataSourceFactory, dribbbleSourceFactory) - return SearchDataSourcesRegistry(factories) + factoriesRegistry.dataSourceFactories.value.orEmpty() + return SearchDataSourcesFactory(factories) } } diff --git a/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactoriesRegistry.kt b/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactoriesRegistry.kt new file mode 100644 index 000000000..8fc6a9038 --- /dev/null +++ b/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourceFactoriesRegistry.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.plaidapp.core.interfaces + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData + +private const val designerNewsSearchDataSourceFactoryProviderClassName = + "io.plaidapp.designernews.domain.search.DesignerNewsSearchFactoryProvider" + +// TODO add dribbble as well +private val factoryClassNames = + listOf(designerNewsSearchDataSourceFactoryProviderClassName) + +class SearchDataSourceFactoriesRegistry { + + private val _dataSourceFactories = + MutableLiveData>(getAlreadyAvailableDataSourceFactories()) + + val dataSourceFactories: LiveData> + get() = _dataSourceFactories + + fun add(dataSourceFactory: SearchDataSourceFactory) { + val existingDataSources = _dataSourceFactories.value.orEmpty().toMutableList() + existingDataSources.add(dataSourceFactory) + _dataSourceFactories.postValue(existingDataSources) + } + + fun remove(dataSourceFactory: SearchDataSourceFactory) { + val existingDataSources = _dataSourceFactories.value.orEmpty().toMutableList() + existingDataSources.remove(dataSourceFactory) + _dataSourceFactories.postValue(existingDataSources) + } + + private fun getAlreadyAvailableDataSourceFactories(): List { + return factoryClassNames.map { + val clazz = Class.forName(it) + val instance = clazz.newInstance() as SearchFactoryProvider + instance.getFactory() + } + } +} diff --git a/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesRegistry.kt b/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesFactory.kt similarity index 89% rename from core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesRegistry.kt rename to core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesFactory.kt index 1c82d7cf7..6c41a658b 100644 --- a/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesRegistry.kt +++ b/core/src/main/java/io/plaidapp/core/interfaces/SearchDataSourcesFactory.kt @@ -16,7 +16,7 @@ package io.plaidapp.core.interfaces -class SearchDataSourcesRegistry(private val factories: List) { +class SearchDataSourcesFactory(private val factories: List) { fun buildSearchDataSources(query: String): List = factories.map { it.buildDataSource(query) } diff --git a/core/src/main/java/io/plaidapp/core/interfaces/SearchFactoryProvider.kt b/core/src/main/java/io/plaidapp/core/interfaces/SearchFactoryProvider.kt new file mode 100644 index 000000000..a60ddec9c --- /dev/null +++ b/core/src/main/java/io/plaidapp/core/interfaces/SearchFactoryProvider.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2019 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.plaidapp.core.interfaces + +interface SearchFactoryProvider { + + fun getFactory(): SearchDataSourceFactory +} diff --git a/designernews/src/main/java/io/plaidapp/designernews/dagger/DesignerNewsSearchComponent.kt b/designernews/src/main/java/io/plaidapp/designernews/dagger/DesignerNewsSearchComponent.kt new file mode 100644 index 000000000..05931629c --- /dev/null +++ b/designernews/src/main/java/io/plaidapp/designernews/dagger/DesignerNewsSearchComponent.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2019 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.plaidapp.designernews.dagger + +import dagger.Component + +@Component( + modules = [SearchDataModule::class] +) +interface DesignerNewsSearchComponent diff --git a/designernews/src/main/java/io/plaidapp/designernews/dagger/Injector.kt b/designernews/src/main/java/io/plaidapp/designernews/dagger/Injector.kt index 15517c842..e71ab78ab 100644 --- a/designernews/src/main/java/io/plaidapp/designernews/dagger/Injector.kt +++ b/designernews/src/main/java/io/plaidapp/designernews/dagger/Injector.kt @@ -22,6 +22,7 @@ import `in`.uncod.android.bypass.Bypass import android.util.TypedValue import androidx.core.content.ContextCompat import io.plaidapp.core.dagger.MarkdownModule +import io.plaidapp.designernews.domain.search.DesignerNewsSearchFactoryProvider import io.plaidapp.designernews.ui.login.LoginActivity import io.plaidapp.designernews.ui.story.StoryActivity import io.plaidapp.ui.coreComponent @@ -62,3 +63,8 @@ fun inject(activity: LoginActivity) { .build() .inject(activity) } + +fun DesignerNewsSearchFactoryProvider.inject() { + + DaggerDesignerNewsSearchComponent.create() +} diff --git a/designernews/src/main/java/io/plaidapp/designernews/dagger/SearchDataModule.kt b/designernews/src/main/java/io/plaidapp/designernews/dagger/SearchDataModule.kt new file mode 100644 index 000000000..d01e6a17f --- /dev/null +++ b/designernews/src/main/java/io/plaidapp/designernews/dagger/SearchDataModule.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2019 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.plaidapp.designernews.dagger + +import dagger.Module +import dagger.Provides +import io.plaidapp.core.dagger.DataSourcesModule +import io.plaidapp.core.designernews.data.stories.StoriesRepository +import io.plaidapp.core.interfaces.SearchDataSourceFactoriesRegistry +import io.plaidapp.designernews.domain.search.DesignerNewsSearchDataSourceFactory + +@Module(includes = [DataSourcesModule::class]) +class SearchDataModule { + + @Provides + fun designerNewsSearchDataSourceFactory( + repository: StoriesRepository, + registry: SearchDataSourceFactoriesRegistry + ): DesignerNewsSearchDataSourceFactory { + val factory = DesignerNewsSearchDataSourceFactory(repository) + registry.add(factory) + return factory + } +} diff --git a/core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsDataSource.kt b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsDataSource.kt similarity index 96% rename from core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsDataSource.kt rename to designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsDataSource.kt index 52b627f3a..4a1eb846d 100644 --- a/core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsDataSource.kt +++ b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsDataSource.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.plaidapp.core.interfaces.designernews +package io.plaidapp.designernews.domain.search import io.plaidapp.core.data.PlaidItem import io.plaidapp.core.data.Result diff --git a/core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsSearchDataSourceFactory.kt b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchDataSourceFactory.kt similarity index 89% rename from core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsSearchDataSourceFactory.kt rename to designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchDataSourceFactory.kt index 4be2f1a4c..6b26c0ce9 100644 --- a/core/src/main/java/io/plaidapp/core/interfaces/designernews/DesignerNewsSearchDataSourceFactory.kt +++ b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchDataSourceFactory.kt @@ -14,15 +14,14 @@ * limitations under the License. */ -package io.plaidapp.core.interfaces.designernews +package io.plaidapp.designernews.domain.search import io.plaidapp.core.designernews.data.DesignerNewsSearchSource import io.plaidapp.core.designernews.data.stories.StoriesRepository import io.plaidapp.core.interfaces.PlaidDataSource import io.plaidapp.core.interfaces.SearchDataSourceFactory -import javax.inject.Inject -class DesignerNewsSearchDataSourceFactory @Inject constructor( +class DesignerNewsSearchDataSourceFactory( private val repository: StoriesRepository ) : SearchDataSourceFactory { diff --git a/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchFactoryProvider.kt b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchFactoryProvider.kt new file mode 100644 index 000000000..27711f515 --- /dev/null +++ b/designernews/src/main/java/io/plaidapp/designernews/domain/search/DesignerNewsSearchFactoryProvider.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2019 Google, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.plaidapp.designernews.domain.search + +import io.plaidapp.core.designernews.data.stories.StoriesRepository +import io.plaidapp.core.interfaces.SearchDataSourceFactory +import io.plaidapp.core.interfaces.SearchFactoryProvider +import io.plaidapp.designernews.dagger.inject +import javax.inject.Inject + +class DesignerNewsSearchFactoryProvider : SearchFactoryProvider { + + init { + inject() + } + + @Inject + lateinit var repository: StoriesRepository + + override fun getFactory(): SearchDataSourceFactory { + return DesignerNewsSearchDataSourceFactory(repository) + } +} diff --git a/core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleDataSource.kt b/dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleDataSource.kt similarity index 96% rename from core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleDataSource.kt rename to dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleDataSource.kt index 200f8e693..b8edd1efb 100644 --- a/core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleDataSource.kt +++ b/dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleDataSource.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.plaidapp.core.interfaces.dribbble +package io.plaidapp.dribbble.domain.search import io.plaidapp.core.data.PlaidItem import io.plaidapp.core.data.Result diff --git a/core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleSearchDataSourceFactory.kt b/dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleSearchDataSourceFactory.kt similarity index 89% rename from core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleSearchDataSourceFactory.kt rename to dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleSearchDataSourceFactory.kt index d50e69d78..cd8583e7b 100644 --- a/core/src/main/java/io/plaidapp/core/interfaces/dribbble/DribbbleSearchDataSourceFactory.kt +++ b/dribbble/src/main/java/io/plaidapp/dribbble/domain/search/DribbbleSearchDataSourceFactory.kt @@ -14,15 +14,14 @@ * limitations under the License. */ -package io.plaidapp.core.interfaces.dribbble +package io.plaidapp.dribbble.domain.search import io.plaidapp.core.dribbble.data.DribbbleSourceItem import io.plaidapp.core.dribbble.data.ShotsRepository import io.plaidapp.core.interfaces.PlaidDataSource import io.plaidapp.core.interfaces.SearchDataSourceFactory -import javax.inject.Inject -class DribbbleSearchDataSourceFactory @Inject constructor( +class DribbbleSearchDataSourceFactory( private val repository: ShotsRepository ) : SearchDataSourceFactory { diff --git a/search/src/main/java/io/plaidapp/search/domain/SearchUseCase.kt b/search/src/main/java/io/plaidapp/search/domain/SearchUseCase.kt index 1af66e237..e4e9f23ac 100644 --- a/search/src/main/java/io/plaidapp/search/domain/SearchUseCase.kt +++ b/search/src/main/java/io/plaidapp/search/domain/SearchUseCase.kt @@ -20,15 +20,15 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import io.plaidapp.core.data.PlaidItem import io.plaidapp.core.data.Result -import io.plaidapp.core.interfaces.SearchDataSourcesRegistry +import io.plaidapp.core.interfaces.SearchDataSourcesFactory import io.plaidapp.core.ui.getPlaidItemsForDisplay class SearchUseCase( - dataSourcesRegistry: SearchDataSourcesRegistry, + dataSourcesFactory: SearchDataSourcesFactory, query: String ) { - private val dataSources = dataSourcesRegistry.buildSearchDataSources(query) + private val dataSources = dataSourcesFactory.buildSearchDataSources(query) private val _searchResult = MutableLiveData>() val searchResult: LiveData> diff --git a/search/src/main/java/io/plaidapp/search/ui/SearchViewModel.kt b/search/src/main/java/io/plaidapp/search/ui/SearchViewModel.kt index 900d90975..2fb3001c8 100644 --- a/search/src/main/java/io/plaidapp/search/ui/SearchViewModel.kt +++ b/search/src/main/java/io/plaidapp/search/ui/SearchViewModel.kt @@ -24,7 +24,7 @@ import androidx.lifecycle.viewModelScope import io.plaidapp.core.data.CoroutinesDispatcherProvider import io.plaidapp.core.feed.FeedProgressUiModel import io.plaidapp.core.feed.FeedUiModel -import io.plaidapp.core.interfaces.SearchDataSourcesRegistry +import io.plaidapp.core.interfaces.SearchDataSourcesFactory import io.plaidapp.search.domain.SearchUseCase import kotlinx.coroutines.launch @@ -33,7 +33,7 @@ import kotlinx.coroutines.launch * for display in the [SearchActivity]. */ class SearchViewModel( - private val dataSourcesRegistry: SearchDataSourcesRegistry, + private val dataSourcesFactory: SearchDataSourcesFactory, private val dispatcherProvider: CoroutinesDispatcherProvider ) : ViewModel() { @@ -42,7 +42,7 @@ class SearchViewModel( private val searchQuery = MutableLiveData() private val results = Transformations.switchMap(searchQuery) { - searchUseCase = SearchUseCase(dataSourcesRegistry, it) + searchUseCase = SearchUseCase(dataSourcesFactory, it) loadMore() return@switchMap searchUseCase?.searchResult } diff --git a/search/src/main/java/io/plaidapp/search/ui/SearchViewModelFactory.kt b/search/src/main/java/io/plaidapp/search/ui/SearchViewModelFactory.kt index 192bae71b..63555de58 100644 --- a/search/src/main/java/io/plaidapp/search/ui/SearchViewModelFactory.kt +++ b/search/src/main/java/io/plaidapp/search/ui/SearchViewModelFactory.kt @@ -19,14 +19,14 @@ package io.plaidapp.search.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import io.plaidapp.core.data.CoroutinesDispatcherProvider -import io.plaidapp.core.interfaces.SearchDataSourcesRegistry +import io.plaidapp.core.interfaces.SearchDataSourcesFactory import javax.inject.Inject /** * Factory to create [SearchViewModel] */ class SearchViewModelFactory @Inject constructor( - private val dataSourcesRegistry: SearchDataSourcesRegistry, + private val dataSourcesFactory: SearchDataSourcesFactory, private val dispatcherProvider: CoroutinesDispatcherProvider ) : ViewModelProvider.Factory { @@ -35,6 +35,6 @@ class SearchViewModelFactory @Inject constructor( if (modelClass != SearchViewModel::class.java) { throw IllegalArgumentException("Unknown ViewModel class") } - return SearchViewModel(dataSourcesRegistry, dispatcherProvider) as T + return SearchViewModel(dataSourcesFactory, dispatcherProvider) as T } }