Skip to content

Commit 35b26ef

Browse files
extract extensions for Koin DSL / Integration into Activity
1 parent 149c1d8 commit 35b26ef

File tree

4 files changed

+98
-88
lines changed

4 files changed

+98
-88
lines changed
Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,60 @@
11
package com.example.nav3recipes.modular.koin
22

3-
import androidx.navigation3.runtime.NavEntry
3+
import androidx.compose.runtime.Composable
44
import androidx.navigation3.runtime.entry
5-
import androidx.navigation3.runtime.entryProvider
65
import com.example.nav3recipes.modular.hilt.EntryProviderInstaller
7-
import org.koin.androidx.scope.dsl.activityRetainedScope
6+
import org.koin.core.annotation.KoinInternalApi
7+
import org.koin.core.definition.KoinDefinition
8+
import org.koin.core.module.KoinDslMarker
9+
import org.koin.core.module.Module
10+
import org.koin.core.module._scopedInstanceFactory
11+
import org.koin.core.module._singleInstanceFactory
12+
import org.koin.core.qualifier.named
13+
import org.koin.core.scope.Scope
14+
import org.koin.dsl.ScopeDSL
815
import org.koin.dsl.module
916

1017
val appModule = module {
18+
includes(profileModule,conversationModule)
1119

12-
activityRetainedScope {
20+
scope<KoinModularActivity> {
1321
scoped {
1422
Navigator(startDestination = ConversationList)
1523
}
24+
}
25+
}
1626

17-
scoped {
18-
val navigator = get<Navigator>()
19-
val navigationSet = hashSetOf<EntryProviderInstaller>()
20-
navigationSet.add {
21-
entry<ConversationList> {
22-
//TODO make it private
23-
ConversationListScreen(
24-
onConversationClicked = { conversationDetail ->
25-
navigator.goTo(conversationDetail)
26-
}
27-
)
28-
}
29-
}
30-
navigationSet.add {
31-
entry<ConversationDetail> { key ->
32-
//TODO make it private
33-
ConversationDetailScreen(key) { navigator.goTo(Profile) }
34-
}
35-
}
36-
navigationSet.add {
37-
entry<Profile>{
38-
//TODO make it private
39-
ProfileScreen()
40-
}
41-
}
42-
navigationSet
27+
@KoinDslMarker
28+
fun Scope.navigator(): Navigator = get<Navigator>()
29+
30+
//TODO Need typealias EntryProviderInstaller = EntryProviderBuilder<Any>.() -> Unit-
31+
32+
@KoinDslMarker
33+
@OptIn(KoinInternalApi::class)
34+
inline fun <reified T : Any> ScopeDSL.navigation(
35+
noinline definition: @Composable Scope.(T) -> Unit,
36+
): KoinDefinition<EntryProviderInstaller> {
37+
val def = _scopedInstanceFactory<EntryProviderInstaller>(named<T>(), {
38+
val scope = this
39+
{
40+
entry<T>(content = {definition(scope,it)})
4341
}
42+
}, scopeQualifier)
43+
module.indexPrimaryType(def)
44+
return KoinDefinition(module, def)
45+
}
4446

45-
scoped<(Any) -> NavEntry<Any>> {
46-
val navigationSet = get<HashSet<EntryProviderInstaller>>()
47-
entryProvider { navigationSet.forEach { builder -> this.builder() } }
47+
@KoinDslMarker
48+
@OptIn(KoinInternalApi::class)
49+
inline fun <reified T : Any> Module.navigation(
50+
noinline definition: @Composable Scope.(T) -> Unit,
51+
): KoinDefinition<EntryProviderInstaller> {
52+
val def = _singleInstanceFactory<EntryProviderInstaller>(named<T>(), {
53+
val scope = this
54+
{
55+
entry<T>(content = {definition(scope,it)})
4856
}
49-
}
57+
})
58+
indexPrimaryType(def)
59+
return KoinDefinition(this, def)
5060
}

app/src/main/java/com/example/nav3recipes/modular/koin/ConversationModule.kt

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,8 @@ import androidx.compose.ui.Alignment
2020
import androidx.compose.ui.Modifier
2121
import androidx.compose.ui.graphics.Color
2222
import androidx.compose.ui.unit.dp
23-
import androidx.navigation3.runtime.entry
24-
import com.example.nav3recipes.modular.hilt.EntryProviderInstaller
25-
import com.example.nav3recipes.modular.hilt.Navigator
26-
import com.example.nav3recipes.modular.hilt.Profile
2723
import com.example.nav3recipes.ui.theme.colors
28-
import dagger.Module
29-
import dagger.Provides
30-
import dagger.hilt.InstallIn
31-
import dagger.hilt.android.components.ActivityRetainedComponent
32-
import dagger.multibindings.IntoSet
24+
import org.koin.dsl.module
3325

3426
// API
3527
object ConversationList
@@ -38,30 +30,26 @@ data class ConversationDetail(val id: Int) {
3830
get() = colors[id % colors.size]
3931
}
4032

41-
// IMPL
42-
//@Module
43-
//@InstallIn(ActivityRetainedComponent::class)
44-
//object ConversationModule {
45-
//
46-
// @IntoSet
47-
// @Provides
48-
// fun provideEntryProviderInstaller(navigator: Navigator): EntryProviderInstaller =
49-
// {
50-
// entry<ConversationList> {
51-
// ConversationListScreen(
52-
// onConversationClicked = { conversationDetail ->
53-
// navigator.goTo(conversationDetail)
54-
// }
55-
// )
56-
// }
57-
// entry<ConversationDetail> { key ->
58-
// ConversationDetailScreen(key) { navigator.goTo(Profile) }
59-
// }
60-
// }
61-
//}
33+
val conversationModule = module {
34+
scope<KoinModularActivity> {
35+
navigation<ConversationList> {
36+
ConversationListScreen(
37+
onConversationClicked = { conversationDetail ->
38+
navigator().goTo(conversationDetail)
39+
}
40+
)
41+
}
42+
43+
navigation<ConversationDetail> { key ->
44+
ConversationDetailScreen(key) {
45+
navigator().goTo(com.example.nav3recipes.modular.koin.Profile)
46+
}
47+
}
48+
}
49+
}
6250

6351
@Composable
64-
fun ConversationListScreen(
52+
private fun ConversationListScreen(
6553
onConversationClicked: (ConversationDetail) -> Unit
6654
) {
6755
LazyColumn(
@@ -91,7 +79,7 @@ fun ConversationListScreen(
9179
}
9280

9381
@Composable
94-
fun ConversationDetailScreen(
82+
private fun ConversationDetailScreen(
9583
conversationDetail: ConversationDetail,
9684
onProfileClicked: () -> Unit
9785
) {

app/src/main/java/com/example/nav3recipes/modular/koin/KoinModularActivity.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
package com.example.nav3recipes.modular.koin
22

3+
import android.content.ComponentCallbacks
34
import android.os.Bundle
45
import androidx.activity.ComponentActivity
56
import androidx.activity.compose.setContent
67
import androidx.compose.foundation.layout.padding
78
import androidx.compose.material3.Scaffold
89
import androidx.compose.ui.Modifier
910
import androidx.navigation3.runtime.NavEntry
11+
import androidx.navigation3.runtime.entryProvider
1012
import androidx.navigation3.ui.NavDisplay
13+
import com.example.nav3recipes.modular.hilt.EntryProviderInstaller
1114
import com.example.nav3recipes.ui.setEdgeToEdgeConfig
15+
import org.koin.android.ext.android.get
16+
import org.koin.android.ext.android.getKoin
17+
import org.koin.android.ext.android.getKoinScope
1218
import org.koin.android.ext.android.inject
1319
import org.koin.android.ext.koin.androidContext
1420
import org.koin.android.scope.AndroidScopeComponent
1521
import org.koin.androidx.scope.activityRetainedScope
22+
import org.koin.compose.getKoin
23+
import org.koin.core.annotation.KoinInternalApi
1624
import org.koin.core.context.startKoin
1725
import org.koin.core.context.stopKoin
26+
import org.koin.core.parameter.ParametersDefinition
27+
import org.koin.core.qualifier.Qualifier
1828
import org.koin.core.scope.Scope
1929
import org.koin.mp.KoinPlatform
2030

@@ -32,10 +42,24 @@ import org.koin.mp.KoinPlatform
3242
* The app module creates the navigator by supplying a start destination and provides this navigator
3343
* to the rest of the app module (i.e. MainActivity) and the feature modules.
3444
*/
45+
46+
typealias EntryProvider = (Any) -> NavEntry<Any>
47+
48+
@OptIn(KoinInternalApi::class)
49+
inline fun ComponentCallbacks.entryProvider(
50+
mode: LazyThreadSafetyMode = LazyThreadSafetyMode.SYNCHRONIZED,
51+
) : Lazy<EntryProvider> = lazy(mode) { val entries = getKoinScope().getAll<EntryProviderInstaller>()
52+
val entryProvider: (Any) -> NavEntry<Any> = entryProvider {
53+
entries.forEach { builder -> this.builder() }
54+
}
55+
entryProvider
56+
}
57+
3558
class KoinModularActivity : ComponentActivity(), AndroidScopeComponent {
59+
3660
override val scope : Scope by activityRetainedScope()
3761
val navigator: Navigator by inject()
38-
val entryProvider: (Any) -> NavEntry<Any> by inject()
62+
val entryProvider : EntryProvider by entryProvider()
3963

4064
override fun onCreate(savedInstanceState: Bundle?) {
4165
super.onCreate(savedInstanceState)

app/src/main/java/com/example/nav3recipes/modular/koin/ProfileModule.kt

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,21 @@ import androidx.compose.runtime.Composable
1111
import androidx.compose.ui.Alignment
1212
import androidx.compose.ui.Modifier
1313
import androidx.compose.ui.unit.dp
14-
import androidx.navigation3.runtime.entry
15-
import com.example.nav3recipes.modular.hilt.EntryProviderInstaller
16-
import dagger.Module
17-
import dagger.Provides
18-
import dagger.hilt.InstallIn
19-
import dagger.hilt.android.components.ActivityRetainedComponent
20-
import dagger.multibindings.IntoSet
14+
import org.koin.dsl.module
2115

2216
// API
2317
object Profile
2418

25-
// IMPLEMENTATION
26-
//@Module
27-
//@InstallIn(ActivityRetainedComponent::class)
28-
//object ProfileModule {
29-
//
30-
// @IntoSet
31-
// @Provides
32-
// fun provideEntryProviderInstaller() : EntryProviderInstaller = {
33-
// entry<Profile>{
34-
// ProfileScreen()
35-
// }
36-
// }
37-
//}
19+
val profileModule = module {
20+
scope<KoinModularActivity> {
21+
navigation<Profile> {
22+
ProfileScreen()
23+
}
24+
}
25+
}
3826

3927
@Composable
40-
fun ProfileScreen() {
28+
private fun ProfileScreen() {
4129
val profileColor = MaterialTheme.colorScheme.surfaceVariant
4230
Column(
4331
modifier = Modifier

0 commit comments

Comments
 (0)