Koin share dependencies scoped to nested graph
Asked Answered
R

1

7

I'm wondering how to properly scope dependencies with Koin library.

Since Google recommends a single Activity architecture the AndroidX Navigation lib has become a key library to facilitate this by easily swapping Fragments.

A typical modern Android app has multiple features separated in packages and/or Gradle modules.
These feature modules provides a graph that can be used in the root graph as nested graphs. (See picture)

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_graph"
    app:startDestination="@id/mainFragment">

    <include app:graph="@navigation/nav_graph_feature_a" />
    <include app:graph="@navigation/nav_graph_feature_b" />

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.androidx_navigation.MainFragment"
        android:label="MainFragment"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_mainFragment_to_featureAFragment1"
            app:destination="@id/nav_graph_feature_a" />
        <action
            android:id="@+id/action_mainFragment_to_featureBFragment1"
            app:destination="@id/nav_graph_feature_b" />
    </fragment>
</navigation>

Koin scoping of feature modules

Following rules should be respected:

  • Every layer represent a scope.
  • Inner layers can inject anything defined in outer layers.
  • Layers that do not have an overlap should not be able to inject each other's dependencies.
  • Leaving a layer should dispose of its dependencies.

More concretely:

  • FeatureA can inject Activity and App dependencies, but not FeatureB dependencies
  • FeatureB can inject Activity and App dependencies, but not FeatureA dependencies

How to achieve this in Koin?

Note that sharing dependencies is not limited to ViewModel only.
I should be able to share any arbitrary class within my scope.

Rich answered 24/12, 2020 at 13:38 Comment(1)
I also created a starter demo project that you can use to get started on a solution. github.com/timrijckaert/koin/tree/unclear-unload-per-feature/…Rich
A
4

Actually, I think you can use loadModule and unLoadModule in your feature Modules and with some layer modules like network uiKit and ... control their needs.

FeatureA can inject Activity and App dependencies, but not FeatureB dependencies

I think this is not reasonable that inject your appModule in the FeatueA, you can have a coreModule and add this in your all modules that needed, also you can find your activity with requireActivity() in your fragmnet for example:D, so the FeatureA never can inject FeatureB dependencies, because they have no access to each other.

Anna answered 31/12, 2020 at 14:20 Comment(5)
I played already with load- unloadModule, but was unable to make it work with permission change/process death. Mind that once a module is initialised it can not be re added with loadModule. Also consider navigating to FeatureA and then back to FeatureB I will be able to inject FeatureA dependencies if I can not unload the FeatureAModule first. Please give it a try with the provided sample if you wantRich
You can try and fork github.com/timrijckaert/koin/tree/unclear-unload-per-feature/… To see if your idea worksRich
Why you should inject FeatureA dependencies when it's not present(navigating to FeatureA and then back to FeatureB )? I will definitely take a look at the project at the first opportunity.Anna
You misunderstand what I mean.Rich
When you navigate to FeatureA en only call loadModules navigating to FeatureB will still have access to FeatureA dependencies if you don't call unloadModules somewhere.Rich

© 2022 - 2024 — McMap. All rights reserved.