Skip to content

Commit

Permalink
Add lazyViewModelForClass to get ViewModel lazily in custom classes
Browse files Browse the repository at this point in the history
  • Loading branch information
NinoDLC committed Feb 1, 2024
1 parent 845060d commit 9bc826d
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.koin.sample.sandbox.components.main

class SimpleServiceImpl() : SimpleService {
class SimpleServiceImpl : SimpleService {
override val id: String = SERVICE_IMPL
}
const val SERVICE_IMPL = "DefaultService"
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.koin.sample.sandbox.main

import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import org.koin.androidx.viewmodel.ext.android.lazyViewModelForClass
import org.koin.sample.sandbox.components.mvvm.SimpleViewModel

class MainCustomView(
context: Context,
attrs: AttributeSet? = null,
) : AppCompatTextView(context, attrs) {

private val viewModel: SimpleViewModel by lazyViewModelForClass(viewModelStoreOwnerLazy = { findViewTreeViewModelStoreOwner()!! })

override fun onAttachedToWindow() {
super.onAttachedToWindow()

text = viewModel.id
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@
android:layout_height="wrap_content"
android:text="Next"/>

<org.koin.sample.sandbox.main.MainCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,26 @@ fun <T : ViewModel> getLazyViewModelForClass(
scope = scope
)
}
}

@OptIn(KoinInternalApi::class)
@MainThread
inline fun <reified T : ViewModel> lazyViewModelForClass(
crossinline viewModelStoreOwnerLazy: () -> ViewModelStoreOwner,
scope: Scope = GlobalContext.get().scopeRegistry.rootScope,
qualifier: Qualifier? = null,
noinline state: BundleDefinition? = null,
key: String? = null,
noinline parameters: ParametersDefinition? = null,
): Lazy<T> = lazy(LazyThreadSafetyMode.NONE) {
val viewModelStoreOwner = viewModelStoreOwnerLazy()
resolveViewModel(
vmClass = T::class,
viewModelStore = viewModelStoreOwner.viewModelStore,
extras = state?.invoke()?.toExtras(viewModelStoreOwner) ?: CreationExtras.Empty,
qualifier = qualifier,
parameters = parameters,
key = key,
scope = scope
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.koin.test.android.viewmodel.ext.android

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelStoreOwner
import io.mockk.mockk
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.androidx.viewmodel.ext.android.lazyViewModelForClass
import org.koin.core.context.startKoin
import org.koin.dsl.module

class ViewModelLazyTest {
@Test
fun `lazyViewModelForClass shouldn't resolve ViewModelStoreOwner immediately`() {
// Given
startKoin {
modules(
module {
viewModelOf(::FooViewModel)
}
)
}

var resolved = false
val viewModelStoreOwnerResolver: () -> ViewModelStoreOwner = {
resolved = true
mockk(relaxed = true)
}

// When
val lazy: Lazy<FooViewModel> = lazyViewModelForClass(viewModelStoreOwnerLazy = viewModelStoreOwnerResolver)

// Then
assertFalse(resolved)
lazy.value
assertTrue(resolved)
}

private class FooViewModel : ViewModel()
}

0 comments on commit 9bc826d

Please sign in to comment.