tornadofx
tornadofx copied to clipboard
Support for creating components using constructor via dependency injection
koin supports inject with a constructor, which is a good way to describe exactly what is needed without code bloat, especially when there are quite a few class properties
But tornadofx itself creates its components through an empty constructor, without using di container
init di container
FX.dicontainer = object : DIContainer, KoinComponent {
override fun <T : Any> getInstance(type: KClass<T>): T =
getKoin().get(clazz = type, qualifier = null, parameters = null)
}
example of view
class LoginView(windowController: WindowController, windowView: WindowView) : View("Auth") {
override val root = vbox {
windowView.root
}
}
error
SEVERE: Uncaught error
java.lang.InstantiationException: dev.talosdx.pentaquark.view.auth.LoginView
at java.lang.Class.newInstance(Class.java:427)
at tornadofx.FXKt.find(FX.kt:434)
at tornadofx.FXKt.find$default(FX.kt:423)
at tornadofx.App.start(App.kt:83)
I do not know all the subtleties, but I can suggest this option FX.kt
fun <T : Component> find(type: KClass<T>, scope: Scope = FX.defaultScope, params: Map<*, Any?>? = null): T {
...
val cmp = dicontainer?.getInstance(type) ?: type.java.newInstance()
...
}
can also modify the interface DiContainer by adding a default method
fun <T : Any> newInstance(type: KClass<T>): T = type.java.newInstance()
Where you really need to get a new object every time.
I have code like this, instead of parameters in the constructor, you can use this:
class LineChart24Hours : Fragment() {
val titleChart: String by param("") // default value
val titleAxisY: String by param("")
val tickUnitStart: Double by param(100.0)
val lowerBound: Double by param(0.0)
val upperBound: Double by param(0.0)
val isAutoRanging: Boolean by param(true)
val isForceZeroInRange: Boolean by param(false)
}
class ViewTestChar() : View() {
val chart: LineChart24Hours by fragment(
params = mapOf(
LineChart24Hours::upperBound.name to 10000.0,
LineChart24Hours::titleAxisY.name to "Title"
)
)
also why don't you want to inject controllers and view?
Firstly, this is validation, when the compiler checks (in the case of koin) everything that is needed before starting the application.
Second is the speed and ease of writing code.
Thirdly, I can change di without any problems, since 90% supports inject via the constructor
Fourth, making such changes should not create problems.
Fifth, we get support for all the possibilities of di
And a thousand more reasons why
if you need exactly koin support: https://edvin.gitbooks.io/tornadofx-guide/content/part2/Dependency_Injection.html
Firstly, this is validation, when the compiler checks (in the case of koin) everything that is needed before starting the application.
my version is also checked in compile time.
Second is the speed and ease of writing code.
this is subjective, people may not use DI at all
Thirdly, I can change di without any problems, since 90% supports inject via the constructor
why change DI? Why not use native DI?
Fourth, making such changes should not create problems.
what problems exactly? How does your option solve them?
Fifth, we get support for all the possibilities of di
what for ?
I would add the ability to inject through the constructor in the native DI, this would really be useful