在 Fragment 中获取与 Activity 中定义的 ViewModel 相同的实例

Hus*_*ain 5 android viewmodel kotlin koin

所以,我用于Koin依赖注入,这是我在活动中所做的

class ModuleDetailActivity : AppCompatActivity() {

    private lateinit var moduleId:String
    private lateinit var levelModule:Level.Module

    private val moduleViewModel: ModuleViewModel by viewModel { parameterOf(moduleId, levelModule) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        ...
        ...

        moduleId = intent.getString("module_id")
        levelModule = intent.getParcelable("level_module")

        ...
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我有多个ModuleDetailActivity可以添加或替换的片段,并且我希望在这些片段中使用相同的实例,moduleViewModel而不在内部传递任何参数Fragment

class ModuleDetailFragment : Fragment() {

    private val moduleViewModel: ModuleViewModel by sharedViewModel()

    ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

我知道这会引发错误,正如预期的那样,您可以看到这个

Caused by: org.koin.core.error.InstanceCreationException: Could not create instance for [Factory:'****.ui.module.ModuleViewModel']
Run Code Online (Sandbox Code Playgroud)

这就是我初始化模块的方式

val viewModelModule = module {
    viewModel { (id : String, levelModule:Level.Module) -> ModuleViewModel(id, levelModule, get()) }
}
Run Code Online (Sandbox Code Playgroud)

有没有什么解决方案可以让我在ModuleViewModel不传递参数的情况下获得定义的内部活动的相同实例Fragment

Isa*_*era 10

使用KOIN

ViewModel 实例可以在 Fragments 及其宿主 Activity 之间共享。

要在 Fragment 中注入共享 ViewModel,请使用:

by sharedViewModel() - lazy delegate property to inject shared ViewModel instance into a property
getSharedViewModel() - directly get the shared ViewModel instance
Run Code Online (Sandbox Code Playgroud)

只需声明一次 ViewModel:

val weatherAppModule = module {

   // WeatherViewModel declaration for Weather View components
   viewModel { WeatherViewModel(get(), get()) }

}
Run Code Online (Sandbox Code Playgroud)

在您的活动中:

class WeatherActivity : AppCompatActivity() {

    /*
     * Declare WeatherViewModel with Koin and allow constructor dependency injection
     */
    private val weatherViewModel by viewModel<WeatherViewModel>()
}
Run Code Online (Sandbox Code Playgroud)

在你的片段中:

class WeatherHeaderFragment : Fragment() {

    /*
     * Declare shared WeatherViewModel with WeatherActivity
     */
    private val weatherViewModel by sharedViewModel<WeatherViewModel>()
}
Run Code Online (Sandbox Code Playgroud)

其他片段:

class WeatherListFragment : Fragment() {

    /*
     * Declare shared WeatherViewModel with WeatherActivity
     */
    private val weatherViewModel by sharedViewModel<WeatherViewModel>()
}
Run Code Online (Sandbox Code Playgroud)


Chi*_*oni 0

您应该按如下方式初始化viewModel

class ModuleDetailActivity : AppCompatActivity() {

    private val moduleId: String by lazy {
        intent.getString("module_id")
    }

    private val levelModule: Level.Module by lazy {
        intent.getParcelable("level_module")
    }

    private val moduleViewModel: ModuleViewModel by viewModel {
        parameterOf(moduleId, levelModule)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        ...
        ...

        viewModel.doYourStuff()

        ...
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我们应该只对普通 Java 对象使用get()or 。inject()为了注入ViewModel,他们提供了单独的方式viewModel()

不知道为什么它不适合你。