Skip to content

Instantly share code, notes, and snippets.

@marcellogalhardo
Created February 12, 2021 13:28
Show Gist options
  • Save marcellogalhardo/cac5013015c62ea8178739963526688a to your computer and use it in GitHub Desktop.
Save marcellogalhardo/cac5013015c62ea8178739963526688a to your computer and use it in GitHub Desktop.
A simple SystemServiceLocator that enables to easy customization of Context `getSystemService`.
class MainApplication : Application() {
private val component = MainComponent.Factory.create(application = this)
private val locator = SystemServiceLocator {
register { component.getFragmentFactory() }
}
override fun getSystemService(name: String): Any? {
return locator.getSystemService(name) ?: super.getSystemService(name)
}
override fun getSystemServiceName(serviceClass: Class<*>): String? {
return locator.getSystemServiceName(serviceClass)
?: super.getSystemServiceName(serviceClass)
}
}
class MainApplication : Application() {
private val component = MainComponent.Factory.create(application = this)
private val locator = SystemServiceLocator {
register { component.getNavigationChannel() }
register { component.getFragmentFactory() }
}
override fun getSystemService(name: String): Any? {
return locator.getSystemService(name) ?: super.getSystemService(name)
}
override fun getSystemServiceName(serviceClass: Class<*>): String? {
return locator.getSystemServiceName(serviceClass)
?: super.getSystemServiceName(serviceClass)
}
}
class MainActivity : FragmentHostActivity(HomeFragment::class) {
override fun onCreate(savedInstanceState: Bundle?) {
supportFragmentManager.fragmentFactory = application.getSystemService()!!
super.onCreate(savedInstanceState)
}
}
class SystemServiceLocator(
private val serviceInstanceMap: Map<String, () -> Any>,
private val serviceNameMap: Map<Class<*>, String>,
) {
fun getSystemService(name: String): Any? = serviceInstanceMap[name]?.invoke()
fun getSystemServiceName(serviceClass: Class<*>): String? = serviceNameMap[serviceClass]
}
fun SystemServiceLocator(block: SystemServiceRegistry.() -> Unit): SystemServiceLocator {
val registry = SystemServiceRegistry().apply(block)
return SystemServiceLocator(registry.serviceInstanceMap, registry.serviceNameMap)
}
class SystemServiceRegistry {
@PublishedApi
internal val serviceInstanceMap = mutableMapOf<String, () -> Any>()
@PublishedApi
internal val serviceNameMap = mutableMapOf<Class<*>, String>()
inline fun <reified T : Any> register(noinline getService: () -> T) {
val name = T::class.java.simpleName
serviceInstanceMap[name] = getService
serviceNameMap[T::class.java] = name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment