Add the dependency below to your module's build.gradle.kts
file:
Module | Version |
---|---|
leviathan | |
leviathan-compose |
sourceSets {
commonMain.dependencies {
// core library
implementation("io.github.composegears:leviathan:$version")
// Compose integration
implementation("io.github.composegears:leviathan-compose:$version")
}
}
Use same dependencies in the dependencies { ... }
section
Create Module
(recommend to use object
) and extends from Leviathan
class
Create fields using one functions:
- Use
by instanceOf
to create single-object-delegate (same instance upon every access) - Use
by lateInitInstance
to create instance-based late-init dependency (ps: you need to callprovides
method before access) - Use
by factoryOf
to create factory-delegate (new instance upon each access)
Both functions return a dependency provider instance and the type of field will be Dependency<Type>
To retreive dependency use either Module.dependency.get()
or define a property val dep by Module.dependency
Declare you dependencies
class SampleRepository()
class SampleRepositoryWithParam(val param: Int)
class SampleRepositoryWithDependency(val dependency: SampleRepository)
interface SampleInterfaceRepo
class SampleInterfaceRepoImpl : SampleInterfaceRepo
Create module
object Module : Leviathan() {
val lazyRepository by instanceOf(::SampleRepository)
val nonLazyRepository by instanceOf(false, ::SampleRepository)
val repositoryWithParam by factoryOf { SampleRepositoryWithParam(1) }
val repositoryWithDependency by instanceOf { SampleRepositoryWithDependency(lazyRepository.get()) }
val interfaceRepo by instanceOf<SampleInterfaceRepo>(::SampleInterfaceRepoImpl)
}
Dependencies usage:
fun foo() {
val repo = Module.lazyRepository.get()
//...
}
class Model(
val dep1: SampleRepository = Module.lazyRepository.get()
) {
val dep2: SampleRepository by Module.nonLazyRepository
//...
}
Interface based approach
// ----------Module 1-------------
//Dependency
class Dep {
fun foo() {}
}
// ----------Module 2-------------
// Dependency provider interface
interface ICore {
val dep: Dependency<Dep>
}
// Dependency provider implementation
internal class CoreImpl : Leviathan(), ICore {
override val dep by instanceOf { Dep() }
}
// Dependency provider accessor
val Core: ICore = CoreImpl()
// ----------Module 3-------------
// Usage
fun boo() {
val dep by Core.dep
}
Simple approach
// ----------Module 1-------------
//Dependency
class Dep {
fun foo() {}
}
// ----------Module 2-------------
// Dependency provider & accessor
object Core : Leviathan() {
val dep by instanceOf { Dep() }
}
// ----------Module 3-------------
// Usage
fun boo() {
val dep by Core.dep
}
In order to create good & testable classes recommend to use advanced scenario
- declare dependencies
class DataRepository //... class ApiRepository //...
- declare module interface (data/domain modules)
interface DataModule { val dataRepository: Dependency<DataRepository> } interface ApiModule { val apiRepository: Dependency<ApiRepository> }
- Create
AppModule
and inherit from interfaces(step #2) andLeviathan
object AppModule : DataModule, ApiModule, Leviathan() { override val dataRepository: Dependency<DataRepository> by instance(::DataRepository) override val apiRepository: Dependency<ApiRepository> by instance(::ApiRepository) }
- Create Models (or any other classes) base on interfaces from step #2
class Model(apiModule: ApiModule = AppModule){ val api: ApiRepository by apiModule.apiRepository fun foo(){/*...*/} }
Now you can make tests and have easy way to mock your data:
@Test
fun ModelTests() {
val model = Model(object : Leviathan(), ApiModule {
override val apiRepository by instanceOf { MyMockApiRepository() }
})
model.foo()
//-----or-----------
AppModule.apiRepository.overrideWith { MyMockApiRepository() }
val model = Model()
model.foo()
}
Dependencies access in compose code:
class Repository(){
fun foo(){}
}
object Module : Leviathan(){
val dependency by instanceOf { Repository() }
}
@Composable
fun SomeComposable(){
val dependency = leviathanInject { Module.dependency }
///...
}
Thank you for your help! ❤️
Developed by ComposeGears 2024
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.