【问题标题】:how to inject View model using koin? (for specific use case)如何使用 koin 注入 View 模型? (针对特定用例)
【发布时间】:2019-06-26 05:58:32
【问题描述】:

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

我的视图模型需要在从 Activity 实例化时传递参数(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:无法启动活动 组件信息{com.andor.navigate.notepad/com.andor.navigate.notepad.listing.NotesActivity}: org.koin.core.error.InstanceCreationException:无法创建 例如 [类型:工厂,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:无法创建实例 [类型:工厂,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 的新手。

【问题讨论】:

    标签: android dependency-injection koin


    【解决方案1】:

    在应用程序类中初始化 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)
    

    【讨论】:

    • 你能再读一遍我的问题吗?我知道如何注入 viewModel,但我有一个我想解决的特定情况。
    • 我已经在上面尝试过并遇到了我在问题中发布的崩溃
    【解决方案2】:

    您不应该在ViewModel 构造函数中传递这些类型的参数。相反,您可以在 Activity 的 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)
    }
    

    }

    【讨论】:

    猜你喜欢
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多