<@U0BLRBFMM>, is Kodein usable just in library mod...
# kodein
j
@salomonbrys, is Kodein usable just in library modules? I’ve integrated it just in a library module but don’t want my app (android) module to know anything about it, since it’d be a library used by third parties. I’m getting this compile time error:
s
How did you import the Kodein-DI lib in your library module's gradle file ?
j
implementation “org.kodein.dikodein di generic jvm$kodein_version” implementation “org.kodein.dikodein di framework android$kodein_version”
don’t want it to be
api
since don’t want to expose its APIs to the third party, if possible
my lib has proper access to the Kodein classes etc, everything is alright but then I get the mentioned compile time error. I solve it by adding those deps to the app module (I’ve tried and works) but that’s something I’d want to avoid at all cost
s
Can you try with
api
, just to see if it fixes the issue ?
j
don’t want third parties to require Kodein
api
also fixes it, at least for a local gradle third party module
I assume it’d also work for external third parties that fetch our library whenever we deploy it to maven central
s
Well, Kodein needs to be in the classpath of the app
j
ideally, the
app
module (working as a third party here) would never need to fetch Kodein
s
I see. That is not possible. Kodein needs to be in the class path.
j
do you think something could be done to workaround that ?
as in opening a PR to Kodein if needed
to remove that requirement somehow
s
No. That is simply not possible. If a library uses Kodein, the app runing the lib must contain the Kodein code.
Cano you try to declare the dep with
runtimeOnly
instead of
implementation
?
Forget it, bad idea
Won't work
j
ok
no, it does not work 😄
so why is it impossible?
s
According to this, using
implementation
should work, as the app should fetch it for runtime, not for compile time : https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_configurations_graph
j
🤷‍♂️
s
Oh. Just saw that you are getting a compile time error. I thought it was a runtime error 😛
j
it’s a compile time one 🙂
s
I see. So let's start again (sorry).
j
ok hehe, no worries
s
So : this is expected. There's no way to fix it, other than NOT having your library classes be
KodeinAware
.
j
for now I got it to work just with 2 approaches: • explicitly add the Kodein deps into the third party: Given it’s a library we have and we’re using Kodein in house just for our benefit on architecting it, we’d want to not expose it. • Use
api
for Kodein deps inside our lib so they get exposed to the third party classpath. Doable but not ideal since third party would not need to even see those in the auto complete etc
that could work
I mean, what would be the equivalent setup without using KodeinAware?
s
In essence, this is not a huge limitation: instead of:
Copy code
class Whatever(override val kodein: Kodein) : KodeinAware {
  val myDep: MyDep by instance()
}
Do:
Copy code
class Whatever(private val kodein: Kodein) {
  val myDep: MyDep by kodein.instance()
}
j
the thing is it’s android 😄
can I just create a kodein manually in the application class or something ? can’t get it passed in
s
Then it's a tad more complex:
Copy code
class Whatever {
  val myDep: MyDep by lazy { kodein().direct.instance() }
}
And, if you want to be a bit more optimised:
Copy code
class Whatever {
  val kodein by lazy { appKodein() }
  val myDep: MyDep by lazy { kodein.direct.instance() }
}
Also, you can use the dependency holder pattern : http://kodein.org/Kodein-DI/?6.1/android#dependency-holder
j
I see, I’ll take a look, thanks!
s
Finally, you could create a "local dependency holder":
Copy code
class Whatever {
  private class Deps(override val kodein: Kodein) : KodeinAware {
    val myDep: MyDep by instance()
  }
  private val deps: Deps by lazy { Deps(kodein()) }
}
Any of these should work 😛 Keep me posted 😉
j
sure, thx 🙂
yep, looks like it compiles
s
\o/ Which solution did you implemented ?
j
for now just the simple one without de holder
s
👍
j
just trying out things, as soon as everything is working (fixing some runtime erros I had on the implementation now) I’d iterate it towards the holder pattern if possible
that by lazy seems to be returning a viewModelFactory
sorry
s
?
j
a
KodeinProperty<Deps>
how can I get access to the actual item ?
private val deps: Deps by lazy { Deps(kodein()) }}
s
use
.direct
j
where? not available over the property
s
Can you show me the code ?
j
(might be bc we’re using 5.0.0)
Copy code
val kodein by lazy {
        Kodein { import(appModule(Deps())) }
 }
private val viewModelFactory by lazy { kodein.instance<ViewModelProvider.Factory>(tag = AppQualifier) }

...
override fun onCreate() {
    viewModel = getViewModel(viewModelFactory)
}
something like that
s
Copy code
private val viewModelFactory by lazy { kodein.DIRECT.instance<ViewModelProvider.Factory>(tag = AppQualifier) }
j
ah, ok
s
(
.direct
in lowercase, obviously)
j
what does direct exactly ?
s
It returns the required instance, instead of a
KodeinProperty
, which is meant to be used with
by
j
but it stays lazy isn’t it ?
s
Well,
lazy
expects the instance. Using
by instance()
is a way of being lazy without writing
by lazy {}
everytime.
j
ok
makes sense