如何使用koin注入View模型? (针对特定用例)

时间:2019-06-26 05:58:32

标签: android dependency-injection koin

我有一个活动的共享视图模型,它是片段。

从活动实例化时,仅需要传递我的视图模型的参数(onCreate一次)

viewModel =ViewModelProviders.of(this,
                                 NoteViewModelFactory(application!!,
                                                      uid = intent!!.getStringExtra("uid")!!))
                             .get(NoteViewModel::class.java)

但是从片段中我不需要传递参数,因为我确定参数传递了一次。

viewModel = ViewModelProviders.of(activity!!).get(NoteViewModel::class.java)

我在Koin中尝试了以下操作。

val noteModule = module(override = true) {
    viewModel { (id: String) -> NoteViewModel(androidApplication(), id) }
}

活动中:

private val viewModel: NoteViewModel by viewModel { parametersOf(intent!!.getStringExtra("uid")!!) }

在片段中:

private val viewModel: NoteViewModel by sharedViewModel()

应用程序崩溃,出现以下错误:

  

java.lang.RuntimeException:无法启动活动   ComponentInfo {com.andor.navigate.notepad / com.andor.navigate.notepad.listing.NotesActivity}:   org.koin.core.error.InstanceCreationException:无法创建   的实例   [type:Factory,primary_type:'com.andor.navigate.notepad.core.NoteViewModel']           在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)           在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)           在android.app.ActivityThread.-wrap12(ActivityThread.java)           在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1477)           在android.os.Handler.dispatchMessage(Handler.java:102)           在android.os.Looper.loop(Looper.java:154)           在android.app.ActivityThread.main(ActivityThread.java:6119)           在java.lang.reflect.Method.invoke(本机方法)           在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:886)           在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)        原因:org.koin.core.error.InstanceCreationException:无法创建实例   [type:Factory,primary_type:'com.andor.navigate.notepad.core.NoteViewModel']           在org.koin.core.instance.DefinitionInstance.create(DefinitionInstance.kt:61)           在org.koin.core.instance.FactoryDe​​finitionInstance.get(FactoryDe​​finitionInstance.kt:37)           在org.koin.core.definition.BeanDefinition.resolveInstance(BeanDefinition.kt:70)           在org.koin.core.scope.Scope.resolveInstance(Scope.kt:165)

我无法理解如何使用KOIN解决此问题。

P.S:我是koin DI的新手。

2 个答案:

答案 0 :(得分:0)

在应用程序类中初始化koin时有什么问题吗?我没有任何麻烦地尝试了您的代码。我正在使用koin版本2.0.1

class App : Application() {

    override fun onCreate() {
        super.onCreate()

        val noteModule = module(override = true) {
            viewModel { (id: String) -> NoteViewModel(androidApplication(), id) }
        }

        startKoin {
            androidContext(this@App)
            modules(
                noteModule
            )
        }
    }

}

活动和片段:

class MainActivity : AppCompatActivity() {

    private val viewModel: NoteViewModel by viewModel { parametersOf(intent!!.getStringExtra("uid")) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Log.d("NoteViewModel", "id: ${viewModel.id}")

        supportFragmentManager.beginTransaction().replace(R.id.main_root, Frag()).commit()
    }

}
class Frag : Fragment() {

    private val viewModel: NoteViewModel by sharedViewModel()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        Log.d("NoteViewModel", "id: ${viewModel.id}")
        return inflater.inflate(R.layout.activity_main, container, false)
    }
}

查看模型类:

class NoteViewModel (application: Application, val id: String) : AndroidViewModel(application)

答案 1 :(得分:0)

您不应在ViewModel构造函数中传递这些类型的参数。相反,您可以做的是在“活动”的onCreate()上,将传递的值设置为ViewModel。因此,当您访问片段中的ViewModel时,肯定会设置该值。

class NoteViewModel (application: Application) : AndroidViewModel(application)
{
    var id:String = ""   
}

您的koin模块:

val noteModule = module(override = true) {
    viewModel { NoteViewModel(androidApplication()) }
}

活动:

class MainActivity : AppCompatActivity() {

    private val viewModel: NoteViewModel by viewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        viewModel.id = intent?.getStringExtra("uid")?: ""

        supportFragmentManager.beginTransaction().replace(R.id.container, MyFrag()).commit()
    }
}

片段:

class MyFrag : Fragment() {

private val viewModel: NoteViewModel by sharedViewModel()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    // your value will be available here.
    return inflater.inflate(R.layout.activity_main, container, false)
}

}