DGDependency Graph
Fieldnotes

ENGINEERING NOTE / 2026-08-18

Match Compose injection scopes to real UI ownership

Recomposition, navigation, and process lifetime are different events; a dependency scope must say which one it follows.

Compose makes it easy to request an object close to the UI that uses it. Proximity is useful, but it does not define ownership. Recomposition can call a function many times. Navigation can keep or discard a back-stack entry. The operating system can recreate the process. A sound scope names the event that owns the object.

Separate retrieval from creation

Ask two questions for each injected object:

  1. Where is the object retrieved?
  2. Which lifecycle creates and releases it?

A repository retrieved by a composable can still be process-scoped. A screen model can be owned by a navigation destination. A transient formatter can be created for each request. Write the lifetime next to the definition and test that the object survives, or does not survive, the intended event.

The Koin Compose reference supports direct injection, ViewModel integration, navigation support, and dynamic modules. It also recommends default-parameter injection as a way to keep a composable easy to test. Review the current Koin for Compose reference before selecting an API because package and lifecycle support can change.

Be careful with dynamic modules

Loading a module when a composable enters composition can be appropriate for a self-contained feature. It can also couple module lifetime to a rendering detail. If two screens use the same definitions, unloading from one screen can surprise the other. Document whether a module belongs to the process, navigation graph, destination, or a feature session.

Test the exit path

Most scope tests prove that an object exists. Also test the exit event:

  • leave and return to a destination;
  • rotate or recreate the host where applicable;
  • remove a back-stack entry;
  • sign out of a session; and
  • run two feature instances with different parameters.

The useful result is not “Koin returned an object.” It is “the same owner receives the same instance until this named event, and a new owner does not receive it.”