ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Understanding Android Scopes with Koin

Components Lifecycle in Android is one of the biggest pain points for Android developers. Let’s add dependency injection complexity with scope management over that … and you can go into a very complex and frustrating situation😭

What is a Scope? What do you mean by Android Scope and how to deal with it? Let’s come back to those concepts to better understand them.

⚠️ The following APIs shown below will be available in Koin 3.0.1 & 2.3.0 ⚠️ Check the last release notes at https://insert-koin.io/blog

This article is inspired by Manuel Vivo’s article, Scoping in Android and Hilt. Manuel has shown how it works for Dagger Hilt. I will explain here how it works for Koin.

What is a scope?

A scope/is a fixed duration of time or method calls in which an object exists. In other words, a scope is a context under which a given key refers to the same instance. Another way to look at this is to think of scope as the amount of time an object’s state persists. When the scope context ends, any objects bound under that scope are said to be /out of scope/and cannot be injected again in other instances.
— Dependency Injection by Dhanji R. Prasanna

In a nutshell, a scope is a space where we are maintaining instances for a specific duration of time. What about Android scope? We maintain instances for the duration of an Android component lifecycle.

Android components have their own lifecycle (Activity, Fragment, Service …). Each property inside those instances follows the underlying component’s lifecycle. In other words, your properties will be garbage collected at the end of your Android Component lifecycle.

Let’s take a simple example:

The instance of MyPresenter will follow MyActivity instance lifecycle. Once the Activity will finish, the presenter instance will be removed from memory. On new MyActivity instance, the presenter property will receive a new instance.

On configuration changes, both instances are recreated

Let’s declare it with Koin 😃

️Do you need a scope?

If our properties can be dropped at the end of the lifecycle, why do we need to care about scopes? 🤔

We need a scope for the following reasons:

  • keep the same instance of a component, for all other components of the scope
  • keep the same instance alive, for a specific period of time

Here are some regular use-cases of scopes, applied to Android applications:

  • Android Lifecycle scope — instance tied to an Android lifecycle component (Activity, Fragment …)
  • Custom scope — instance kept for a specific duration of time (more than one Activity, i.e: wallet …)

Let’s declare our scope for MyActivity with the scope Koin DSL keyword. By writing scope<MyActivity> , we open a code block to define our scoped instances. Each scoped component will be declared with the scoped keyword.

Defining MyActivity scope, with scoped definitions MyAdapter and MyPresenter

This way we can share our MyPresenter instance with another definition of the scope. We use the get() keyword to resolve the MyPresenter instance for the MyAdapter instance.

Now, in our MyActivity class let’s use the AndroidScopeComponent interface and implement the needed scope property with activityScope() delegate function to activate our scope as follows:

We use the AndroidScopeComponent interface and setup our scope with activityScope() function

📌 By using the AndroidScopeComponent interface, you need to override a scope property. This scope will be automatically used in all default API without doing anything else (inject, get, viewModel…)

📌 the activityScope() delegate function ensures removal of your scoped instances at the end of your Activity lifecycle

Note that Koin also proposes theScopeActivity class, to help wrap the Activity scope declaration. Check the documentation for more details.

However, on configuration changes, we still lose our MyPresenter instance. On a new MyActivity instance, we are creating a new Activity scope.

On configuration changes, both instances are recreated

ViewModel: a game-changer

Since 2017, the Android architecture components are clearly helping to deal with this kind of lifecycle problem by proposing the ViewModel class. This new component will follow your Activity/Fragment instance and survive a configuration change. It simplifies the lifecycle management with only one lifecycle method to implement: onCleared()

A ViewModel is super easy to declare in Koin 😁

The ViewModel instance is handled by an internal Android factory, allowing it to survive configuration changes.

On configuration changes, the MyViewModel instance is kept

Similar Dagger Hilt, there is a special scope to survive configuration changes.

The activityRetainedScope() function will hold instances via a ViewModel holder instance for you.

We can keep our MyPresenter instance, through configuration changes

Every scope has an End

Taking control of scoped instances makes you responsible for closing them. The Koin Scope API helps automatically handle Android scopes for you:

  • the AndroidScopeComponent interface will help setup a scope for your Android component, by using activityScope() or activityRetainedScope() delegates for your scope property
  • ScopeActivity class helps wrap everything for you

The same API exists for Fragment and Service classes. The Fragment scope automatically binds your parent Activity scope. Check the Android Scope documentation for more details: https://insert-koin.io/docs/reference/koin-android/scope

A custom scope helps you maintain an app state for a given duration. Take care to properly setup your create/close sequence. You can check the following documentation for more information about Scope API: https://insert-koin.io/docs/reference/koin-core/scopes

Be sure to use only scoped instances if you really need them. Keep things as simple as possible 👍

From Manuel Vivo’s article:

Scoping can be costly because the provided object stays in memory until the holder is destroyed. Be thoughtful about the use of scoped objects in your application.

Thank you Manuel Vivo for your very helpful feedback 🙏

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Arnaud Giuliani

Lead of #Koin framework (insert-koin.io) - Co-founder of Kotzilla (kotzilla.io) - Google Dev Expert #Kotlin - #AndroidDev

No responses yet

Write a response