标签: koin

如何在 Kotlin 中使用 Koin 注入 ViewModel?

我们如何使用 Koin 为 ViewModel 注入依赖项?

所以例如,我有一个ViewModel这样的:

class SomeViewModel(val someDependency: SomeDependency, val anotherDependency: AnotherDependency): ViewModel()
Run Code Online (Sandbox Code Playgroud)

现在这里的官方文档指出,要提供一个ViewModel我们可以执行以下操作:

val myModule : Module = applicationContext {

    // ViewModel instance of MyViewModel
    // get() will resolve Repository instance
    viewModel { SomeViewModel(get(), get()) }

    // Single instance of SomeDependency
    single<SomeDependency> { SomeDependency() }

    // Single instance of AnotherDependency
    single<AnotherDependency> { AnotherDependency() }
}
Run Code Online (Sandbox Code Playgroud)

然后注入它,我们可以这样做:

class MyActivity : AppCompatActivity(){

    // Lazy inject SomeViewModel
    val model : SomeViewModel by viewModel()

    override fun …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-viewmodel koin

8
推荐指数
1
解决办法
4442
查看次数

java.lang.IllegalStateException:KoinApplication 尚未启动

我正在使用 koin 学习 kotlin。在目录中运行应用程序时,我看到以下消息。

java.lang.IllegalStateException:KoinApplication 尚未启动

虽然我在 MyApplication 中使用了startKoin

class MyApplication : Application() {

    var listOfModules = module {
        single { GitHubServiceApi() }
    }

    override fun onCreate() {
        super.onCreate()

        startKoin {
            androidLogger()
            androidContext(this@MyApplication)
            modules(listOfModules)
        }

    }

} 
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我发现了我犯了错误的问题。我应该在 mainfest.xml 中添加 MyApplcation 名称

在此输入图像描述

kotlin koin

8
推荐指数
3
解决办法
5976
查看次数

如何在单元测试中获取上下文以在内存数据库对象中创建 Room 数据库

我正在尝试在执行数据库插入的应用程序存储库类中测试这个函数。我正在Koin用作我的依赖注入库。为了进行测试,我需要创建一个内置于内存的数据库版本。要创建该数据库,我需要 Android 应用程序上下文。所以我创建了我的测试类,如下所示。

import android.content.Context
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.platform.app.InstrumentationRegistry
import com.chathuranga.shan.mycontacts.di.applicationModule
import com.chathuranga.shan.mycontacts.di.repositoryModule
import com.chathuranga.shan.mycontacts.room.AppDatabase
import org.junit.After
import org.junit.Test

import org.junit.Before
import org.junit.Rule
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.loadKoinModules
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.dsl.module
import org.koin.test.KoinTest
import org.koin.test.inject
import org.mockito.MockitoAnnotations

class ContactRepositoryTest : KoinTest {

    private val contactRepository: ContactRepository by inject()
    private lateinit var appDatabase: AppDatabase

    @get:Rule
    val rule = InstantTaskExecutorRule()

    @Before
    fun setUp() {

        startKoin {
            printLogger()
            modules(listOf(applicationModule,repositoryModule))
        }

        MockitoAnnotations.initMocks(this)

        val context = ApplicationProvider.getApplicationContext<Context>() …
Run Code Online (Sandbox Code Playgroud)

android unit-testing kotlin koin

8
推荐指数
1
解决办法
3308
查看次数

使用 Clean Architecture、MVVM 和 Koin 向数据源提供上下文的正确方法是什么?

我正在使用 Kotlin 开发一个 Android 应用程序,我需要在其中获取移动设备的当前位置。我已经在各种示例中找到了一种方法,但我不知道如何根据 Clean Architecture 与 MVVM 集成此逻辑。

在我的架构中,我有以下几层:表示层、用例层、数据层、域层和框架层。我用 MVVM 模式组织了表示层。我还使用 Koin 进行依赖注入。

我从框架层中的数据源获取应用程序所需的所有数据。例如,远程获取的数据或从数据库获取的数据,或设备(位置)提供的数据。

以下是从 ViewModel 获取位置所涉及的文件示例:

ConfigurationViewModel(表示层):

class ConfigurationViewModel(private val useCase: GetLocationUseCase) : ViewModel() {

    fun onSearchLocationButtonClicked() = liveData<Resource<Location>>(Dispatchers.IO) {
        emit(Resource.loading())
        try {
            emit(Resource.success(data = useCase.invoke(UseCase.None())))
        } catch (exception: Exception) {
            emit(Resource.error(message = exception.message))
        }
    }
Run Code Online (Sandbox Code Playgroud)

GetLocationUseCase(用例层):

class GetLocationUseCase(private val locationRepository: LocationRepository) :
    UseCase<Location, UseCase.None>() {

    override suspend fun invoke(params: None): Location = locationRepository.getLocation()
}
Run Code Online (Sandbox Code Playgroud)

LocationRepositoryImpl(数据层):

class LocationRepositoryImpl(private val locationDeviceDataSource: LocationDeviceDataSource) :
    LocationRepository {
    override suspend fun …
Run Code Online (Sandbox Code Playgroud)

android mvvm kotlin clean-architecture koin

8
推荐指数
1
解决办法
2267
查看次数

如何使用可组合项内的参数初始化 Koin 视图模型?

我的视图模型模块如下所示:

val viewModelModule = module {
    viewModel { (id: Int, user: String, email: String) ->
        MyViewModel(get(), get(), id = id, user = user, email = email)
    }
}
Run Code Online (Sandbox Code Playgroud)

因此视图模型总共接受五个参数,前两个是存储库,下面是它们的模块:

val firstRepositoryModule = module {
    single {
        FirstRepository()
    }
}
Run Code Online (Sandbox Code Playgroud)
val secondRepositoryModule = module {
    single {
       SecondRepository()
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这个示例代码,但这里的视图模型不接受任何参数,所以它不能回答我的问题

android viewmodel kotlin koin

8
推荐指数
1
解决办法
3945
查看次数

如何使用Koin管理用户范围?

我正在尝试使用Koin创建用户范围。记录用户时,我正在创建范围:

val scope = getKoin().createScope("USER_SCOPE")
Run Code Online (Sandbox Code Playgroud)

当用户单击注销时,我正在破坏范围

    scope?.let {userScope ->
        userScope.close()
        getKoin().deleteScope(userScope.id)
    }
Run Code Online (Sandbox Code Playgroud)

在我的koin模块中,我有一个scopedUserRepository,它只能在用户会话期间使用。我也有使用此存储库的ViewModels和Use Cases,我尝试将存储库注入scoped其中

val appModule = module {
    scoped<UserRepository> { UserDataRepository() }
    viewModel { UserViewModel(getScope("USER_SCOPE").get()) }
    factory { MyUseCase(getScope("USER_SCOPE").get()) }
}
Run Code Online (Sandbox Code Playgroud)

第一次登录时,它可以正常工作,我在视图模型和用例中注入了用户存储库。但是在注销(删除作用域)之后和再次登录后,UserRepository实例仍然完全相同。

我会在示波器用法中错过某些东西吗?

android kotlin koin

7
推荐指数
1
解决办法
366
查看次数

如何使用 Koin 在 BaseFragment 中注入 viewModel

我创建了一个抽象BaseFragment类,它将被其他具体Fragment类扩展。我想注入ViewModelBaseFragment使用的Koin. 这是我的 BaseFragment:

abstract class BaseFragment<out VM : BaseViewModel, DB : ViewDataBinding>(private val mViewModelClass: Class<VM>) : Fragment() {

    val viewModel: VM by viewModel()

    open lateinit var binding: DB

    fun init(inflater: LayoutInflater, container: ViewGroup) {
        binding = DataBindingUtil.inflate(inflater, getLayoutRes(), container, false)
    }

    open fun init() {}
    @LayoutRes
    abstract fun getLayoutRes(): Int

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View {
        init(inflater, container!!)
        init()
        super.onCreateView(inflater, container, savedInstanceState)
        return binding.root
    }

    open …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-viewmodel koin

7
推荐指数
1
解决办法
3570
查看次数

在 Koin 中提供一个实例作为它的接口

假设我有两个接口,例如:

interface LetterClassifier
interface NumberClassifier
Run Code Online (Sandbox Code Playgroud)

然后这些接口将应用于这个类:

class Classifier() : LetterClassifier, NumberClassifier
Run Code Online (Sandbox Code Playgroud)

现在,我想提供这些实例只是作为LetterClassifierNumberClassifier不作为ClassifierKoin

我认为这样做的方法是:

module {
    val classifier = Classifier()

    single<NumberClassifier> { classifier }
    single<LetterClassifier> { classifier }
}
Run Code Online (Sandbox Code Playgroud)

但我不认为这是正确的方法。有人可以指导我吗?

kotlin koin

7
推荐指数
2
解决办法
3000
查看次数

如何通过 Koin 提供具有接口的 ViewModel

我有以下 ViewModel 设置:

interface FooViewModel {}

class FooViewModelImpl: ViewModel(), FooViewModel {}
Run Code Online (Sandbox Code Playgroud)

我想通过 Koin 提供它,如下所示:

viewModel<FooViewModel> { FooViewModelImpl() }
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为 Koin 在定义中需要 ViewModel 而不是 FooViewModel,而且我不想让我的 FooViewModel 成为从 ViewModel 扩展的抽象类。

有什么办法可以通过 Koin 做到这一点吗?

android interface viewmodel koin

7
推荐指数
1
解决办法
2208
查看次数

Koin 共享范围为嵌套图的依赖项

我想知道如何使用 Koin 库正确确定依赖范围。

由于 Google 推荐了单一Activity架构,因此AndroidX 导航库已成为通过轻松交换Fragments来促进这一点的关键库。

典型的现代 Android 应用程序在包和/或Gradle模块中具有多个分离的功能。
这些功能模块提供了一个可以在根图中用作嵌套图的图。(见图)

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_graph"
    app:startDestination="@id/mainFragment">

    <include app:graph="@navigation/nav_graph_feature_a" />
    <include app:graph="@navigation/nav_graph_feature_b" />

    <fragment
        android:id="@+id/mainFragment"
        android:name="com.example.androidx_navigation.MainFragment"
        android:label="MainFragment"
        tools:layout="@layout/fragment_main">
        <action
            android:id="@+id/action_mainFragment_to_featureAFragment1"
            app:destination="@id/nav_graph_feature_a" />
        <action
            android:id="@+id/action_mainFragment_to_featureBFragment1"
            app:destination="@id/nav_graph_feature_b" />
    </fragment>
</navigation>
Run Code Online (Sandbox Code Playgroud)

功能模块的 Koin 范围

应遵守以下规则:

  • 每层代表一个范围。
  • 内层可以注入外层中定义的任何内容。
  • 没有重叠的层不应该能够注入彼此的依赖关系。
  • 离开一个层应该处理它的依赖项。

更具体地说:

  • FeatureA 可以注入 Activity 和 App 依赖项,但不能注入 FeatureB 依赖项
  • FeatureB 可以注入 Activity 和 App 依赖项,但不能注入 FeatureA 依赖项

如何在 Koin 中实现这一目标?

请注意,共享依赖项不仅限于 ViewModel。
我应该能够在我的范围内共享任何任意类。

android koin android-architecture-navigation navigation-architecture koin-scope

7
推荐指数
1
解决办法
496
查看次数