Skip to content

Instantly share code, notes, and snippets.

@NomenSvyat
Created January 11, 2020 19:18
Show Gist options
  • Save NomenSvyat/58edca4cc96f060418bb528e24e5d382 to your computer and use it in GitHub Desktop.
Save NomenSvyat/58edca4cc96f060418bb528e24e5d382 to your computer and use it in GitHub Desktop.
package com.nomensvyat.di
import timber.log.Timber
import kotlin.reflect.KClass
/**
* Class for managing Dagger components
* */
object ComponentManager {
private val map: MutableMap<Class<out Any>, Any> = mutableMapOf()
/**
* Stores Dagger generated component so it can be then retrieved by it's interface or
* interfaces which component interface extend
*
* @param component Dagger generated component
* */
fun put(component: Any) {
val clazz = component::class.java
clazz.interfaces.forEach { componentInterface ->
map[componentInterface] = component
componentInterface.interfaces.forEach { componentExtends ->
map[componentExtends] = component
}
}
Timber.i("Put: ${clazz.simpleName}")
}
fun <T : Any> get(klass: KClass<T>): T? {
@Suppress("UNCHECKED_CAST")
return map[klass.java] as? T?
}
fun <T : Any> getOrThrow(klass: KClass<T>): T {
return get(klass) ?: throw IllegalStateException("No component for class $klass")
}
fun <T : Any> has(klass: KClass<T>): Boolean = map.containsKey(klass.java)
/**
* Removes from manager instances of [klass] and it's interfaces.
* Passing component's parent
* interfaces will not remove component instance from manager.
* It will just remove mapping for [klass] to component.
* Pass component interface to completely remove component instance from manager.
*
* @param klass component interface
* */
fun <T : Any> remove(klass: KClass<T>) {
val javaClazz = klass.java
Timber.i("Remove: ${javaClazz.simpleName}")
val component = map.remove(javaClazz) ?: return
javaClazz.interfaces.forEach { componentInterface ->
map.removeIfEquals(componentInterface, component)
}
}
fun clear() {
Timber.i("Clearing ComponentManager")
map.clear()
}
}
inline fun <reified T : Any> ComponentManager.getOrThrow(): T = getOrThrow(T::class)
/**
* Removes [key] iff value associated with it is equals to value
* */
private fun <K, V> MutableMap<K, V>.removeIfEquals(key: K, value: V): Boolean =
if (this[key] == value) {
this.remove(key)
true
} else {
false
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment