-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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>() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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