vitaliy
10/22/2020, 2:10 PMSCOPE_USER
. This scope is created when user logs in and I close it on logout. There is a custom by injectUser()
function to inject things from this scope for convenience.
Question: is it possible to link SCOPE_USER
to root when it is created and close it when user logs out? Or should I rather create another SCOPE_GENERAL
for all the stuff, that is currently in root and then link SCOPE_USER
to it? This would require to inject from a scope -> custom by injectGeneric()
function. Ideally linking stuff to root scope would be ideal, but I do no see a way to do it. Or should I rather keep things as they are?
Many thanks for any ideas in advance!Florian Eula
10/26/2020, 8:59 AMviewModel { ThingyVM(handle = get(), ...) }
When injecting it in my fragment, I properly use
override val viewModel: ThingyVM by viewModel(state = { arguments ?: bundleOf() })
Sometimes, maybe like one launch out of 30, I get a crash,
Caused by: org.koin.core.error.NoBeanDefFoundException: No definition found for class:'androidx.lifecycle.SavedStateHandle'. Check your definitions!
at org.koin.core.scope.Scope.throwDefinitionNotFound(Scope.kt:277)
Patrik Åkerfeldt
10/29/2020, 12:56 PM<dependency>
<groupId>org.koin</groupId>
<artifactId>koin-test</artifactId>
<version>2.2.0-beta-1</version>
<scope>test</scope>
</dependency>
I fail to even start the service with error: Kotlin: Cannot access class 'org.koin.core.scope.ScopeInstance'. Check your module classpath for missing or conflicting dependencies
in all places where I use org.koin.ktor.ext.inject
.aipok
10/29/2020, 2:07 PMScopeActivity
and has field defined like this
private val splashVM by scope.viewModel<SplashViewModel>()
it failed with Caused by: java.lang.IllegalStateException: Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.
Am I understand incorrectly that by scope.viewModel
should be called only while I’m calling splashVM
somewhere later in my code? And I only calling splashVM
inside onCreate
but for some reason it still failed and seems to call scope right away on activity init method call.
@arnaud.giuliani should I use it somehow differently now?gps
11/16/2020, 7:23 AMKoinComponent
interface, and then using inject
. I don't need to do this if I'm using it in the context of a route, or application, but I think I do need to do this if I'm using it my own classes? After upgrading to Koin 2.2.0 however, I'm getting a warning asking me to add an annotation: KoinApiExtension
. This suggests to me that I'm likely doing something stupid here. Why is it a bad idea for me to implement KoinComponent
? Thanks!Archie
11/18/2020, 9:19 AMclass Presenter(val view : MyViewContract)
val androidModule = module {
scope<MyActivity> {
// inject current MyActivity
scoped { Presenter(get()) }
}
}
since the activityScope()
is backed inside the ViewModel
:
// Create Activity scope (backed by ViewModel)
override val scope: Scope by lazy { activityScope() }
And the presenter have the reference of the View
wouldn't this leak the Activity
? If I understand it correctly, since the scope
is backed inside a ViewModel
the same instance of Presenter
will be provided when the Activity
did some configuration changes (such as device rotation)... The Activity will be destroyed with its views and a new Activity will be created but.. the presenter is still holding the instance of the destroyed view (View of the Old Activity)...
I am really confuse.Moritz Post
11/18/2020, 10:19 AM@Composable
private fun configureNavigation() {
val navController = rememberNavController()
loadKoinModules(module { single<NavController> { navController } })
}
This has the disadvantage that i have to actively unload the module when the Activity is destroyed.arnaud.giuliani
11/18/2020, 1:26 PMarnaud.giuliani
11/19/2020, 8:41 AMholgerbrandl
11/22/2020, 5:46 PMpawegio
11/25/2020, 2:17 PMMyViewModel
in android Robolectric UI tests:
@get:Rule
val koinTestRule = KoinTestRule.create {
androidContext(testApplication)
modules(listOf(
/* modules */,
module { viewModel(override = true) { mock<MyViewModel> { /* ... */ } },
))
}
I use all-open plugin to open view model class for testing purpose (to perform stubbing):
@AllOpenAnnotation
class MyViewModel(
/* ... */
) : ViewModel()
It throws following exception when fragment scenario launches:
java.lang.NullPointerException
at androidx.lifecycle.ViewModel.setTagIfAbsent(ViewModel.java:157)
at androidx.lifecycle.AbstractSavedStateViewModelFactory.create(AbstractSavedStateViewModelFactory.java:70)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:185)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at org.koin.androidx.viewmodel.ViewModelResolverKt.get(ViewModelResolver.kt:23)
at org.koin.androidx.viewmodel.ViewModelResolverKt.resolveInstance(ViewModelResolver.kt:12)
at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExt.kt:86)
at org.koin.androidx.viewmodel.scope.ScopeExtKt.getViewModel(ScopeExt.kt:72)
at org.koin.androidx.viewmodel.koin.KoinExtKt.getViewModel(KoinExt.kt:41)
at org.koin.androidx.viewmodel.ext.android.FragmentExtKt.getViewModel(FragmentExt.kt:71)
at com.xyz.XYZFragment$$special$$inlined$sharedViewModel$2.invoke(SharedViewModelExt.kt:79)
at kotlin.UnsafeLazyImpl.getValue(Lazy.kt:81)
at com.xyz.XYZFragment.getViewModel(XYZFragment.kt)
any tips?oday
11/30/2020, 10:41 AMdeviant
11/30/2020, 12:06 PMfactory<() -> User>
factory<() -> Location>
koin treat it as same type and failed with this exception:
org.koin.core.error.DefinitionOverrideException: Definition '[Factory:'kotlin.jvm.functions.Function0']' try to override existing definition. Please use override option to fix it
are there any workarounds?Mark
12/04/2020, 3:39 AMMark
12/05/2020, 10:29 AMCoroutineScope
for a Koin Scope
?holgerbrandl
12/05/2020, 7:11 PMimport org.koin.core.KoinComponent
import org.koin.core.context.startKoin
import org.koin.dsl.module
class State<T>(val initialValue: T, name: String? = null)
fun main() {
val sim = module(createdAtStart = true) {
single{ State("red") }
single{ State(false) }
}
startKoin() { modules(sim) }
val koin = (object : KoinComponent {}).getKoin()
val boolState = koin.get<State<Boolean>>()
val stringState = koin.get<State<Boolean>>()
}
but this fails with
Exception in thread "main" org.koin.core.error.DefinitionOverrideException: Definition '[Single:'State']' try to override existing definition. Please use override option or check for definition '[Single:'State']'
kenkyee
12/05/2020, 9:35 PMJoaquim Ley
12/07/2020, 2:48 PMfun initKoin(appDeclaration: KoinAppDeclaration = {}): KoinApplication {
return startKoin {
appDeclaration()
modules(domainModule, remoteModule, dataModule)
}
}
fun startIosKoin(iosModules: List<Module> = emptyList()) = initKoin {
modules(iosModules)
}
Which is called by KoiniOS.kt
private val iosModules: List<Module> = listOf(
storageModule
)
fun inject() = startIosKoin(iosModules)
This storageModule
has iOS specific objects such as NSDefaults
Ths domain module has simple kotlin objects as well data module (repository layer) and the remote module is ktor where I have expect/actual
engines.
(which is called in the AppDelegate KoiniOSKt.inject()
)
-
But for some reason whenever I try to use any use case on iOS it just breaks no NoBeanDefFoundException#<init>(kotlin.String){
Android works fine but iOS can’t use any of the deps, is there something obvious that I am missing or do I need to post more code/plumbing?Saul Wiggin
12/15/2020, 3:29 PMKoinApplication has not been started
deviant
12/16/2020, 12:18 PMtimrijckaert
12/16/2020, 4:58 PMYasutaka Kawamoto
12/25/2020, 2:58 AMbobby
12/29/2020, 1:47 AMsingle{}
? The reason I’m asking this is because when creating EncryptedSharedPreferences
object using single{}
, sometimes it’s throw an Exception, and I want to catch that, prevent the crash app on user side, thanksPhilipp Mayer
12/30/2020, 12:50 PMfun Application.rooms(db: DB) {
install(Koin) {
modules(roomsDI)
}
val roomFooBar: RoomFooBar by inject()
routing {
roomRoutes(roomFooBar)
}
}
val roomsDI = module {
single<RoomFooBar> { RoomService(get()) }
single<RoomRepository> { RoomDatabaseAccessor(???)}
}
class RoomDatabaseAccessor(private val db: DB) : RoomRepository {...}
I'm not sure how to pass the db
parameter (which is a function parameter of Application.rooms()
) into the koin module. The parameter changes depending on the context, so just declaring it inside the module { }
would not work.
Any hints for that? I could not really find a satisfying solution in the docs.
Thanks a lot!timrijckaert
01/03/2021, 9:45 AMnrobi
01/05/2021, 11:24 AMKoinTestRule
example?
I’m trying to use KoinTestRule.create{ }
then koinTestRule.koin.loadModules()
to override some bean definitions with mocks, though I’m bumping into:
java.lang.IllegalStateException: A KoinContext is already started
holgerbrandl
01/05/2021, 9:08 PMtieskedh
01/08/2021, 11:50 PMKshitij Patil
01/16/2021, 2:56 PMcheckModules()
test ? I'm getting can't provide null context to Database object as my viewmodel depends on repository which depends on room database. I tried to follow androidx-samples example from repo but failed to get it workingHelio
01/19/2021, 7:04 AMHelio
01/19/2021, 7:04 AMtynn
01/19/2021, 9:09 AMHelio
01/19/2021, 9:14 AMarnaud.giuliani
01/19/2021, 10:26 AMGlobalContext.get().get()
defaultContext().get()
tynn
01/19/2021, 10:57 AMKoinComponent
should not be necessary then.arnaud.giuliani
01/19/2021, 10:59 AMHelio
01/19/2021, 10:04 PMget()
.
@tynn, in our scenario, we have a Ktor Controller (which is used to declare our apis) and for this specific case we have this “Helper” class, which handle some Generic Top Level functions for us.
For example, in our Controller, we have the following snippet
. There you can see that we are injecting a UseCase class.
fun Route.tokenApi() {
val createAccessTokenUseCase: CreateAccessTokenUseCase by inject()
route("/token") {
post("/build") {
val buildInfo = call.principal<Principal>().getBuildInfo()
createAccessTokenUseCase.createBuildToken(buildInfo,
TokenatorPermissionGroupProvider.getGroupsFor(call.request.local.uri)).let { call.respond(HttpStatusCode.Created, it) }
}
}
This line val buildInfo = call.principal<Principal>().getBuildInfo()
reference our Top level function getBuildInfo()
.
This function will use different classes depending on the Principal
. The way I was doing before, I was injecting the class I wanted in the Controller context and passing it to my function like this getBuildInfo(injectedClassForPrincipal1)
. Complete example:
fun Route.tokenApi() {
val createAccessTokenUseCase: CreateAccessTokenUseCase by inject()
val myInjectedClassForPrincipalOne: MyInjectedClassForPrincipalOne by inject()
route("/token") {
post("/build") {
val buildInfo = call.principal<Principal>().getBuildInfo(myInjectedClassForPrincipalOne)
createAccessTokenUseCase.createBuildToken(buildInfo,
TokenatorPermissionGroupProvider.getGroupsFor(call.request.local.uri)).let { call.respond(HttpStatusCode.Created, it) }
}
}
Soon, we will need to make getBuildInfo()
able to handle a request for a different principal… Which we would need to add another parameter to getBuildInfo(injectedClassForPrincipal1, injectedClassForPrincipal2)
. Complete example:
fun Route.tokenApi() {
val createAccessTokenUseCase: CreateAccessTokenUseCase by inject()
val myInjectedClassForPrincipalOne: MyInjectedClassForPrincipalOne by inject()
val myInjectedClassForPrincipalTwo: MyInjectedClassForPrincipalTwo by inject()
route("/token") {
post("/build") {
val buildInfo = call.principal<Principal>().getBuildInfo(myInjectedClassForPrincipalOne, myInjectedClassForPrincipalTwo)
createAccessTokenUseCase.createBuildToken(buildInfo,
TokenatorPermissionGroupProvider.getGroupsFor(call.request.local.uri)).let { call.respond(HttpStatusCode.Created, it) }
}
}
Using the GlobalContext.get().get(), doesn’t make necessary for me to be injecting class by class. I can just reference them in the Top level functions it should be used. Also, IMHO, I don’t think for this scenario it makes sense to let my TokenController knows about (myInjectedClassForPrincipalOne, myInjectedClassForPrincipalTwo).
Please, let me know if you think it makes sense or if it doesn’t make sense at all (I’m relative new to Kotlin). Also, I’m always keen to hear different point of views.arnaud.giuliani
01/20/2021, 5:08 PMHelio
01/20/2021, 8:11 PM