Skip to content

Commit

Permalink
refactor feature builder
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Apr 23, 2024
1 parent 57b2fb0 commit a0e433e
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,34 @@ inline fun <reified T : ViewModel> daggerViewModel(
)

@Composable
inline fun <reified VM : ViewModel, F : Feature> setupComponent(
inline fun <reified VM : ViewModel, reified F : Feature> setupComponent(
builder: FeatureBuilder<F>,
key: String? = null,
featureKey: Any? = null
): VM {
val context = LocalContext.current

DisposableEffect(Unit) {
builder.create(context.mainUiApi)
builder.setup(
mainUiApi = context.mainUiApi,
key = featureKey
)
onDispose {
builder.clear()
}
}

return daggerViewModel(key) {
builder
.build(context.mainUiApi)
.build<F>(
mainUiApi = context.mainUiApi,
key = featureKey
)
.viewModelFactory
}
}

inline fun <reified VM : ViewModel, F : Feature> NavGraphBuilder.createScreen(
inline fun <reified VM : ViewModel, reified F : Feature> NavGraphBuilder.createScreen(
appDestination: AppDestination,
featureBuilder: FeatureBuilder<F>,
crossinline content: @Composable (VM, List<String>) -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@ import androidx.lifecycle.ViewModelProvider

interface Feature {

/**
* This property is used to get the ViewModelFactory of the feature
* @return ViewModelProvider.Factory
* */
val viewModelFactory: ViewModelProvider.Factory
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,54 @@ package st.slex.csplashscreen.core.ui.di.builder

import st.slex.csplashscreen.core.ui.di.MainUiApi

interface FeatureBuilder<F : Feature> {
abstract class FeatureBuilder<F : Feature> {

var feature: F?
/** This property is used to get the key of the feature */
abstract val key: Any

fun create(mainUiApi: MainUiApi): F
/**
* This method is used to create a new instance of the feature
* @param mainUiApi - the mainUiApi instance
*/
abstract fun create(mainUiApi: MainUiApi): F

fun build(
mainUiApi: MainUiApi
): F = feature ?: create(mainUiApi)
.also { createdFeature ->
feature = createdFeature
}
/**
* This method is used to get the feature from the FeatureCollector
* or create a new instance of the feature and add it to the FeatureCollector
* @param key - the key of the feature
* @param mainUiApi - the mainUiApi instance
*/
inline fun <reified T : F> build(
mainUiApi: MainUiApi,
key: Any? = null,
): T = FeatureCollector.get(keyBuilder(key)) as? T
?: setup(mainUiApi, key) as T

/**
* This method is used to create a new instance of the feature
* and add it to the FeatureCollector
* @param key - the key of the feature
* @param mainUiApi - the mainUiApi instance
*/
fun setup(
mainUiApi: MainUiApi,
key: Any? = null,
): F = create(mainUiApi).also { createdFeature ->
FeatureCollector.add(keyBuilder(key), createdFeature)
}

/**
* This method is used to remove the feature from the FeatureCollector
*/
fun clear() {
feature = null
FeatureCollector.remove(key)
}

/**
* This method is used to get the key of the feature
* @param extraKey - the extra key of the feature
*/
fun keyBuilder(
extraKey: Any?
): Any = extraKey?.let { "$key:$it" } ?: key
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package st.slex.csplashscreen.core.ui.di.builder

object FeatureCollector {

private val features: MutableMap<Any, Feature> = mutableMapOf()

fun get(key: Any): Feature? = features[key]

internal fun add(key: Any, feature: Feature) {
features[key] = feature
}

internal fun remove(key: Any) {
features.remove(key)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import st.slex.csplashscreen.core.network.di.NetworkApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object SingleCollectionBuilder : FeatureBuilder<SingleCollectionComponent> {
object SingleCollectionBuilder : FeatureBuilder<SingleCollectionComponent>() {

override var feature: SingleCollectionComponent? = null
override val key: Any = "single-collection-feature"

override fun create(
mainUiApi: MainUiApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import st.slex.csplashscreen.core.favourite.di.FavouriteApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object FavouriteComponentBuilder : FeatureBuilder<FavouriteComponent> {
object FavouriteComponentBuilder : FeatureBuilder<FavouriteComponent>() {

override var feature: FavouriteComponent? = null
override val key: Any = "favorite-feature"

override fun create(
mainUiApi: MainUiApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import st.slex.csplashscreen.core.photos.di.PhotosApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object HomeComponentBuilder : FeatureBuilder<HomeComponent> {
object HomeComponentBuilder : FeatureBuilder<HomeComponent>() {

override var feature: HomeComponent? = null
override val key: Any = "home-feature"

override fun create(
mainUiApi: MainUiApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import st.slex.csplashscreen.core.photos.di.PhotosApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object ImageDetailComponentBuilder : FeatureBuilder<ImageDetailComponent> {
object ImageDetailComponentBuilder : FeatureBuilder<ImageDetailComponent>() {

override var feature: ImageDetailComponent? = null
override val key: Any = "image-detail-feature"

override fun create(mainUiApi: MainUiApi) = DaggerImageDetailComponent
.factory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import st.slex.csplashscreen.core.network.di.NetworkApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object SearchPhotosComponentBuilder : FeatureBuilder<SearchPhotosComponent> {
object SearchPhotosComponentBuilder : FeatureBuilder<SearchPhotosComponent>() {

override var feature: SearchPhotosComponent? = null
override val key: Any = "search-photos-feature"

override fun create(
mainUiApi: MainUiApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import st.slex.csplashscreen.core.photos.di.PhotosApiBuilder
import st.slex.csplashscreen.core.ui.di.MainUiApi
import st.slex.csplashscreen.core.ui.di.builder.FeatureBuilder

object UserComponentBuilder : FeatureBuilder<UserComponent> {
object UserComponentBuilder : FeatureBuilder<UserComponent>() {

override var feature: UserComponent? = null
override val key: Any = "user-feature"

override fun create(
mainUiApi: MainUiApi
) = feature ?: DaggerUserComponent
override fun create(mainUiApi: MainUiApi) = DaggerUserComponent
.factory()
.create(
dependencies = DaggerUserComponent_UserDependenciesComponent
Expand All @@ -24,7 +22,4 @@ object UserComponentBuilder : FeatureBuilder<UserComponent> {
collectionApi = CollectionApiBuilder.build(mainUiApi)
)
)
.also { component ->
feature = component
}
}

0 comments on commit a0e433e

Please sign in to comment.