Daniel Weidensdörfer
06/22/2023, 7:52 PMArjan van Wieringen
06/23/2023, 1:07 PMDaniel Weidensdörfer
06/23/2023, 6:47 PMval commonClientMain by creating {
dependsOn(commonMain)
dependencies ...
}
val commonClientTest by creating {
dependsOn(commonTest)
dependencies {
implementation(kotlin("test"))
implementation("org.kodein.mock:mockmp-runtime:1.14.0")
implementation("org.kodein.mock:mockmp-test-helper:1.14.0")
}
kotlin.srcDir("build/generated/ksp/jvm/jvmTest/kotlin")
}
I'm not able to successfully make ksp generate the injectMocks function for my custom module. I've tried it with gradle plugin as well as manual configuration. Also it works on the default commonTest. Any ideas?Daniel Weidensdörfer
07/03/2023, 11:18 AMMeika
07/06/2023, 6:43 AMjava.lang.RuntimeException: Invalid TypeToken; must specify type parameters
at our endDaniel Weidensdörfer
07/08/2023, 9:10 AMOlivier Patry
08/17/2023, 1:20 PMbindFactory
.
FTR: I'm in the context of a Jvm Desktop application, unrelated to Android.
I try to keep alive an object bound to a screen, this object is created with bindFactory
taking a parameter specific to the screen being navigated to.
So far, I had no issue, but when moving my window from one screen to another, the whole screen logic was re-triggered (Compose for Desktop context), and thus calling again bindFactory
, how can I reuse the previously created object?Evgeniy Zhelenskiy
08/17/2023, 7:02 PMDrew
09/06/2023, 4:30 PMverify
and checkModules
, was trying to see if something similar existed for Kodein.Stephen Bellanger
09/28/2023, 6:34 AMkodein
and kmm
somebody here that has a repo or example i could check out for setting up kodein
for Android and iOSrocketraman
10/25/2023, 5:40 PMjava.lang.StringIndexOutOfBoundsException: length=2; index=10
at java.lang.String.substring(String.java:2060)
at vg.l.g1(Unknown Source:31)
at myapp.GlobalApplication$di$2$invoke$lambda$0$$inlined$bind$default$1.i(typeTokensJVM.kt:36)
at myapp.GlobalApplication$di$2$invoke$$inlined$singleton$default$7.invoke(typeTokensJVM.kt:15)
at androidx.compose.foundation.text.selection.SelectionMagnifierKt$rememberAnimatedMagnifierPosition$1$2.i(SelectionMagnifier.kt:94)
at bh.g0.i(Unknown Source:169)
at ge.b0.l0(Unknown Source:126)
at kotlinx.coroutines.flow.internal.ChannelFlowTransformLatest$flowCollect$3$1$emit$1.invokeSuspend(Merge.kt)
at kotlin.enums.EnumEntriesList.resumeWith(EnumEntries.kt:7)
at yg.m0.run(Unknown Source:113)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.android.kt:57)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7405)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
Suppressed: dh.g: [l1.m1@82d6cff, f0.e@ec74acc, y1{Cancelling}@96d3115, p0@3b07c2a]
If the line number is right, the exception is thrown from code called by https://github.com/kosi-libs/Kaverit/blob/bbb588d24a686199b0671d0bf5befc5c47797347/kaverit/src/jvmMain/kotlin/org/kodein/type/typeTokensJVM.kt#L36, but that doesn't seem to make much sense.romainbsl
11/18/2023, 5:01 PMArjan van Wieringen
11/22/2023, 6:11 PMkluck
12/06/2023, 4:11 PM@Composable
inline fun <reified T : Container<S, I, A>, S : MVIState, I : MVIIntent, A : MVIAction> storeViewModel(
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
key: String? = null,
extras: CreationExtras = defaultExtras(viewModelStoreOwner),
scope: Scope = getKoinScope(),
noinline parameters: ParametersDefinition? = null,
): StoreViewModel<S, I, A> = getViewModel(qualifier<T>(), viewModelStoreOwner, key, extras, scope, parameters) // -> This is a koin method
What I came up with:
@Composable
fun <S : MVIState, I : MVIIntent, A : MVIAction> storeViewModel(
viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
},
tag: Any? = null,
): StoreViewModel<S, I, A> = with(localDI()) {
getViewModel(viewModelStoreOwner = viewModelStoreOwner, tag = tag, di = this)
}
@Composable
inline fun <reified T : ViewModel> getViewModel(
viewModelStoreOwner: ViewModelStoreOwner,
tag: Any?,
di: DIAware,
): T = resolveViewModel(T::class, viewModelStoreOwner, tag, di)
inline fun <reified T : ViewModel> resolveViewModel(
vmClass: KClass<T>,
viewModelStoreOwner: ViewModelStoreOwner,
tag: Any?,
di: DIAware,
): T {
val factory = di.viewModelFactory(tag)
val provider = ViewModelProvider(
store = viewModelStoreOwner.viewModelStore,
factory = factory,
defaultCreationExtras = defaultExtras(viewModelStoreOwner),
)
return provider[vmClass.java]
}
fun DIAware.viewModelFactory(tag: Any?): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
di.direct.Instance(type = erased(modelClass), tag = tag)
}
It kind-of works, as I manage to retrieve my first store view model (val store = storeViewModel<MainState, MainIntent, MainAction>(tag = MAIN_STORE_TAG)
). But as soon as I try injecting a second one, it retrieves the first one… I use tags to distinguish the two, but I guess there is some erasing stuff that I don't get correctly… Any idea what I could change in my code?
Thanks!Xad Kile
12/18/2023, 8:28 AMelectrolobzik
01/17/2024, 11:46 AMMike Dawson
01/26/2024, 12:39 PM-keep, allowobfuscation, allowoptimization class org.kodein.type.TypeReference
-keep, allowobfuscation, allowoptimization class org.kodein.type.JVMAbstractTypeToken$Companion$WrappingTest
-keep, allowobfuscation, allowoptimization class * extends org.kodein.type.TypeReference
-keep, allowobfuscation, allowoptimization class * extends org.kodein.type.JVMAbstractTypeToken$Companion$WrappingTest
Still getting the runtime exception about an invalid type token when using the version processed via proguard. Works fine without obfuscation. Proguard reduces the package size from 160MB to 80MB, so definitely want to use proguard with KodeIn on JVM if possibleelectrolobzik
01/27/2024, 4:59 PMclass MainActivity : ComponentActivity(), DIAware {
override val di by di()
Right now getting Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly
and looks like AS doesn’t know what is di()
I am using v7.21.2 with main dependency in the common module and kodein-di-framework-android-x
in the androidMain.electrolobzik
01/27/2024, 5:53 PMval user by di.on(session).instance()
I understand that this should do and what it means. But in real life the session
will be nullable and I can’t get user before I get a new session. Looks like I can’t just “open” the scope once the user is authorized, I have to specify the session
each time which is very inconvenient if it’s nullable.diego-gomez-olvera
02/02/2024, 2:18 PMDmitry Danilau
02/26/2024, 6:21 PMOlaf Hoffmann
03/07/2024, 10:02 AMHashMap
throwing a NullPointerException
when Kodein's StandardScopeRegistry
attempts to retrieve a dependency reference from its _cache
inside a synchronizedIfNull
predicate.
For native platforms, the newConcurrentMap
function used to create the _cache
returns a Kotlin Native HashMap. The implementation of this Map shows the code making a non-null assertion on the Map's internal value array. When creating the Map, this array is initialized to `null` and is only allocated when writing a value. Hence, the Exception in this place seems to happen because the Map was never written before reading from it.
What's still puzzling to me is that the only place where _cache
is being written is when the predicate in the registry returns null
. Given that a fresh HashMap should always throw, I'm not sure how the predicate is not always leading to the NPE.
Since this issue occurs on iOS only, I looked into Kodein's platform implementations of maySynchronized
, which is being called internally by synchronizedIfNull
. In the native implementation of that function, the block
passed in is being called immediately without checking the lock
parameter. I assume that's intentional due to missing synchronization facilities in native, but to be fair, it looks suspicious when considering the possibility of a race condition.
While I'm reasonably confident about my findings, this last assumption is merely a guess. Also, it doesn't explain how the `_cache`'s internal array manages to get initialized in the first place when the code suggests that a get
is always the first operation performed on that Map.
I appreciate any help figuring out what's happening here, how we may fix it on our end, or whether this is a problem with the Kodein implementation. For completeness, I've attached the Crashlytics stack trace exported from Firebase so you can investigate it if desired.
Thanks a lot in advance for all your assistance!William Reed
05/21/2024, 5:07 PMrocketraman
09/16/2024, 2:26 PMSet
. Is this a good pattern, or is there a cleaner approach?
singleton { new(::Foo) }.let {
bind<IFace1>().inSet() with it
bind<IFace2>() with it
}
Looks pretty clean to me but want to make sure I'm not missing something.Mari-Mai HENAFF
09/17/2024, 8:20 AMDaniel Weidensdörfer
10/12/2024, 2:11 PMHans van Dodewaard
11/08/2024, 8:53 AMfilipebaptista
02/03/2025, 3:36 PMrocketraman
04/01/2025, 2:11 PMServiceLoader
but is there a "native" way?Vaizin Nikita
05/01/2025, 4:43 PM