{"id":13609092,"url":"https://github.com/deliveryhero/whetstone","last_synced_at":"2026-01-14T01:56:15.857Z","repository":{"id":59916779,"uuid":"402753721","full_name":"deliveryhero/whetstone","owner":"deliveryhero","description":"Whetstone is a dependency injection framework for Android that greatly simplifies working with Dagger 2 using all the powers of Anvil","archived":false,"fork":false,"pushed_at":"2025-11-07T09:44:18.000Z","size":594,"stargazers_count":218,"open_issues_count":9,"forks_count":7,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-11-07T11:25:45.996Z","etag":null,"topics":["android","anvil","dagger2","dependency-injection","kotlin"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deliveryhero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-09-03T11:55:27.000Z","updated_at":"2025-09-03T09:11:23.000Z","dependencies_parsed_at":"2024-01-16T23:31:03.255Z","dependency_job_id":"5cfc5da6-44a5-451b-bc1a-70e384c9808e","html_url":"https://github.com/deliveryhero/whetstone","commit_stats":null,"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"purl":"pkg:github/deliveryhero/whetstone","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deliveryhero%2Fwhetstone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deliveryhero%2Fwhetstone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deliveryhero%2Fwhetstone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deliveryhero%2Fwhetstone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deliveryhero","download_url":"https://codeload.github.com/deliveryhero/whetstone/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deliveryhero%2Fwhetstone/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T00:40:43.272Z","status":"ssl_error","status_checked_at":"2026-01-14T00:40:42.636Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","anvil","dagger2","dependency-injection","kotlin"],"created_at":"2024-08-01T19:01:32.402Z","updated_at":"2026-01-14T01:56:15.851Z","avatar_url":"https://github.com/deliveryhero.png","language":"Kotlin","funding_links":[],"categories":["Kotlin","IoC"],"sub_categories":[],"readme":"[![Maven Central](https://img.shields.io/maven-central/v/com.deliveryhero.whetstone/whetstone?label=stable)](https://central.sonatype.com/artifact/com.deliveryhero.whetstone/whetstone)\n[![Sonatype Snapshot](https://img.shields.io/nexus/s/com.deliveryhero.whetstone/whetstone?server=https%3A%2F%2Foss.sonatype.org\u0026label=snapshot)](https://oss.sonatype.org/content/repositories/snapshots/com/deliveryhero/whetstone/)\n\n# Whetstone\n\n\u003e \"An Anvil forges a Dagger. A Whetstone sharpens it. And when you're not planning on using your Dagger, you may keep it in something that rhymes with kilt.\" — [Tiago Cunha](https://github.com/laggedHero).\n\nWhetstone provides a simplified way to incorporate [Dagger](https://github.com/google/dagger) and [Anvil](https://github.com/square/anvil) into an Android application.\n\nThe goals of Whetstone are:\n\n- To simplify Dagger-related infrastructure for Android apps.\n- To create a standard set of components and scopes to ease setup, but allowing customizations.\n\n## Why would you use Whetstone instead of Hilt?\n\n- All generated code is in Kotlin, which can have significant benefits in a Kotlin only codebase\n- Whetstone avoids KAPT completely for performance reasons by taking advantage of Anvil compiler.\n- Whetstone is extensible by using the powers of Dagger and Anvil.\n- Whetstone significantly reduces boiler plate.\n- Whetstone doesn't do bytecode manipulation for complementing classes. Hilt does.\n- Summarily, while philosophies are similar, whetstone is relatively easier to work with ;). \n\n## Getting Started\n\nFirst you must apply whetstone plugin in the `build.gradle` file of any module that requires dependency injection:\n\n```kotlin\nplugins {\n    id(\"com.deliveryhero.whetstone\").version(\"\u003clatest version\u003e\")\n}\n```\n\nOr you can use the old way to apply a plugin:\n\n```kotlin\n// In root build.gradle.kts\nbuildscript {\n  repositories {\n    mavenCentral()\n  }\n  dependencies {\n    classpath(\"com.deliveryhero.whetstone:whetstone-gradle-plugin:${latest_version}\")\n  }\n}\n\n// In individual modules\napply(plugin = \"com.deliveryhero.whetstone\")\n```\n\nThis automatically configures Dagger and Anvil, and also adds the necessary whetstone dependencies for you.\n\n### Using Snapshot Builds\n\nSnapshot builds are published automatically from the `main` branch and contain the latest unreleased changes. These builds are useful for testing new features or bug fixes before they are officially released.\n\nTo use snapshot builds, add the Sonatype snapshots repository to your project:\n\n```kotlin\n// In root build.gradle.kts or settings.gradle.kts\nrepositories {\n    mavenCentral()\n    maven {\n        url = uri(\"https://oss.sonatype.org/content/repositories/snapshots/\")\n    }\n}\n```\n\nThen use the snapshot version in your plugin dependency:\n\n```kotlin\nplugins {\n    id(\"com.deliveryhero.whetstone\").version(\"\u003cversion\u003e-SNAPSHOT\")\n}\n```\n\nFor example, if the current stable version is `1.1.4`, the snapshot version would be `1.1.5-SNAPSHOT`.\n\n**Note:** Snapshot versions are development builds and may be unstable. Use them at your own risk and only for testing purposes.\n\n## Basic Usage\n\nTo use whetstone, you must initialize it in your Application class.\n\n```kotlin\n@ContributesAppInjector(generateAppComponent = true)\nclass MyApplication : Application(), ApplicationComponentOwner {\n\n    override val applicationComponent by lazy {\n        GeneratedApplicationComponent.create(this)\n    }\n}\n```\n\nNote: For more sophisticated use cases, the generated app component might not be sufficient for you. In such scenario, you can disable automatic generation of app component, and create your own instead.\nAn example may look like this:\n\n```kotlin\n@Singleton // Optional. Can be omitted if you never use this annotation\n@SingleIn(ApplicationScope::class)\n@MergeComponent(ApplicationScope::class)\ninterface MyApplicationComponent : ApplicationComponent {\n\n    @Component.Factory\n    interface Factory {\n        fun create(\n            @BindsInstance application: Application, // this is necessary for whetstone to set things up properly\n            // ...\n        ): MyApplicationComponent\n    }\n}\n```\n\nAfter that, you can easily inject into any Android class (see below).\n\n### Guide\n\nUnlike traditional Dagger, you do not need to define or instantiate Dagger components directly. Instead, we offer predefined components that are generated for you. Whetstone comes with a built-in set of components (and corresponding scope annotations) that are automatically integrated to the Android Framework. As expected, a binding in a child component can have dependencies on any binding in an ancestor component.\n\n### Component Lifecycle\n\nComponent lifetimes are generally bounded by the creation and destruction of a corresponding instance of an important event. The table below lists the scope annotation and bounded lifetime for each component.\n\n| Component            | Scope             | Created At                       | Destroyed At            |\n| -------------------- | ----------------- | -------------------------------- | ----------------------- |\n| ApplicationComponent | @ApplicationScope | Application#onCreate             | Application#onTerminate |\n| ActivityComponent    | @ActivityScope    | Activity#onCreate                | Activity#onDestroy      |\n| FragmentComponent    | @FragmentScope    | FragmentFactory#instantiate      | Fragment#onDestroy      |\n| ViewModelComponent   | @ViewModelScope   | ViewModelProvider.Factory#create | ViewModel#onCleared     |\n| ViewComponent        | @ViewScope        | View#init                        | View#finalize           |\n\n![whetstone-scopes](art/whetstone-scopes.png?raw=true)\n\n### Application\nApplications support field/method injection with Whetstone. Constructor injection is not supported here because the instantiation of applications is completely managed by the system\n\n```kotlin\n@ContributesAppInjector\nclass MyApplication : Application(), ApplicationComponentOwner {\n\n    override val applicationComponent by lazy {\n        TODO(\"Create application component.\")\n    }\n\n    @Inject\n    lateinit var dependency: MyDependency\n\n    fun onCreate() {\n        Whetstone.inject(this)\n        super.onCreate()\n    }\n}\n```\n\n### Activity\nSimilar to applications, activities only support field/method injection\n\n```kotlin\n@ContributesActivityInjector\nclass MainActivity : AppCompatActivity() {\n\n    @Inject\n    lateinit var dependency: MyDependency\n\n    // Get the contributed ViewModel\n    // We automatically handle process death and saved state handle wiring\n    private val viewModel by injectedViewModel\u003cMyViewModel\u003e()\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        Whetstone.inject(this)\n        super.onCreate(savedInstanceState)\n    }\n}\n```\n\n### Service\nServices should be generally avoided when possible. For most cases, work manager can be a great alternative and is highly recommended. See the [workmanager](#workmanager) section for more details about how to use it with Whetstone\n\n```kotlin\n@ContributesServiceInjector\nclass MyService : Service() {\n\n    @Inject\n    lateinit var dependency: MyDependency\n\n    override fun onCreate() {\n        Whetstone.inject(this)\n        super.onCreate()\n    }\n}\n```\n\n### View\n**Disclaimer**: View injection should be avoided by all means. This provision is considered legacy and may be completely removed in a later version of Whetstone.\n\n```kotlin\n@ContributesViewInjector\nclass MyView @JvmOverloads constructor(\n    context: Context,\n    attrs: AttributeSet? = null,\n) : View(context, attrs) {\n\n    @Inject\n    lateinit var dependency: MainDependency\n\n    init {\n        if (!isInEditMode) {\n            Whetstone.inject(this)\n        }\n    }\n}\n```\n\n### Fragments\nFragments support only construction injection, exclusively. This is possible because we are able to hook into the system to influence exactly how fragments should be created. To achieve this, the activity hosting the fragment must install Whetstone's fragment factory.\n\n```kotlin\nclass MyActivity : Activity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        Whetstone.inject(this)\n        super.onCreate(savedInstanceState)\n    }\n}\n```\n\nThen you're able to use the injected fragments with as many constructor arguments as necessary, as long as all these dependencies can be satisfied by dependency injection.\n\n```kotlin\n@ContributesFragment\nclass MyFragment @Inject constructor(\n    private val dependency: MyDependency,\n    private val anotherDependency: AnotherDependency,\n): Fragment() {\n\n    // Get the contributed ViewModel\n    // We automatically handle process death and saved state handle wiring\n    private val viewModel by injectedViewModel\u003cMyViewModel\u003e()\n    private val activityViewModel by injectedActivityViewModel\u003cActivityViewModel\u003e()\n}\n```\n\nNote that all injected fragments must be created via the fragment manager. For example:\n\n```kotlin\nval myFragment = fragmentManager.instantiate\u003cMyFragment\u003e()\n```\n\nFor fragments that don't require any external dependencies, the simple no-arg constructor can still be used, and we gracefully fallback to the default behavior\n\n**Important:** A Fragment should **NEVER** be scoped. The Android Framework controls the Lifecycle of **ALL** Fragments.\n\n### ViewModels\nLike fragments, view models also support full constructor injection\n\n```kotlin\n@ContributesViewModel\nclass MyViewModel @Inject constructor(\n    private val savedStateHandle: SavedStateHandle,\n): ViewModel()\n```\n\n**Important:** A ViewModel should **NEVER** be scoped. The Android Framework controls the Lifecycle of **ALL** ViewModels.\n\n### WorkManager\nWorkmanager integration is an extra add-on, and must be enabled explicitly in your `build.gradle` file before use:\n\n```kotlin\nwhetstone {\n    addOns.workManager.set(true)\n}\n```\n\nThis will automatically install Whetstone's worker factory (replacing the default factory), so that you can immediately start taking advantage of injected workers\n\n```kotlin\n@ContributesWorker\nclass UploadWorker @Inject constructor(\n    @ForScope(WorkerScope::class) context: Context,\n    workerParameters: WorkerParameters,\n    private val dependency: MyDependency,\n): Worker(appContext, workerParameters)\n```\n\nTo disable automatic initialization, you can remove the initializer from your AndroidManifest.xml\n\n```xml\n\u003cprovider\n   android:name=\"androidx.startup.InitializationProvider\"\n   android:authorities=\"${applicationId}.androidx-startup\"\n   android:exported=\"false\"\n   tools:node=\"merge\"\u003e\n   \u003cmeta-data\n       android:name=\"com.deliveryhero.whetstone.worker.WhetstoneWorkerInitializer\"\n       android:value=\"androidx.startup\"\n       tools:node=\"remove\" /\u003e\n\u003c/provider\u003e\n```\n\nHowever, you must make sure to install Whetstone's worker factory before the first call to `WorkManager#getInstance` to avoid breaking the integration. Whetstone provides an injectable `WorkerFactory` that can be used to configure the work manager. For example, you can update your application class to implement work manager's `Configuration.Provider` and supply Whetstone's `WorkerFactory` to the configuration builder\nSee the official [documentation](https://developer.android.com/topic/libraries/architecture/workmanager/advanced/custom-configuration) for more details\n\n### Compose\nCompose integration is an extra add-on, and must be enabled explicitly in your `build.gradle` file before use:\n\n```kotlin\nwhetstone {\n    addOns.compose.set(true)\n}\n```\n\nCurrently, this artefact only exposes APIs for injecting ViewModels that have been contributed to Whetstone\n\n```kotlin\n@Composable\nfun MyScreen(viewModel: MyViewModel = injectedViewModel()) {\n    // injectedViewModel takes care of providing the VM instance directly to this function\n}\n```\n\n## License\n```\nCopyright 2021 Delivery Hero, GmbH.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeliveryhero%2Fwhetstone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeliveryhero%2Fwhetstone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeliveryhero%2Fwhetstone/lists"}