Skip to content

Instantly share code, notes, and snippets.

@themobilecoder
Forked from murki/PlacesActivity.kt
Created June 10, 2021 03:59
Show Gist options
  • Save themobilecoder/5b3648c69802b85e7d9e426648ccf782 to your computer and use it in GitHub Desktop.
Save themobilecoder/5b3648c69802b85e7d9e426648ccf782 to your computer and use it in GitHub Desktop.
The poor man's Dagger: Exemplifying how to implement dependency injection on Android by (ab)using ApplicationContext's getSystemService(). Here we attain inversion of control without the need of any external library. We also use Kotlin's extension methods to provide a friendlier, strongly-typed API to locate dependencies.
class PlacesActivity : AppCompatActivity() {
private lateinit var placesPresenter: PlacesPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// This is how you instantiate your Presenter while the service locator resolves all of its dependencies
// Note that the explicit type argument <PlacesPresenter> is not even necessary since Kotlin can infer the type
placesPresenter = application.getSystemService<PlacesPresenter>()
}
}
class ServiceLocatorApplication : Application() {
/**
* Dependency injection using service locator pattern
*/
override fun getSystemService(name: String?): Any {
// All this logic can be extracted into a separate "Module" class
return when (name) {
// We use the full class' name as the key
PlacesPresenter::class.java.name -> PlacesPresenter(getSystemService<ILocationRepository>(), getSystemService<IPlacesRepository>())
ILocationRepository::class.java.name -> GmsLocationRepository(getSystemService<FusedLocationProviderClient>())
IPlacesRepository::class.java.name -> GmsPlacesRepository(getSystemService<GeoDataClient>())
FusedLocationProviderClient::class.java.name -> LocationServices.getFusedLocationProviderClient(this)
GeoDataClient::class.java.name -> Places.getGeoDataClient(this, null)
else -> super.getSystemService(name)
}
}
}
/**
* Generic strongly-typed extension method for injection
*/
inline fun <reified T : Any> Application.getSystemService() : T {
// We extract the class name from the generic type
return this.getSystemService(T::class.java.name) as T
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment