【问题标题】:What is the point of injecting a ViewModelFactory in Android - Dagger 2在 Android 中注入 ViewModelFactory 有什么意义 - Dagger 2
【发布时间】:2018-07-27 16:57:09
【问题描述】:

我最近开始使用 Android 开发,并且来自 iOS 背景,依赖注入框架和 ViewModelFactories 等概念对我来说是一个新事物。在我看到的所有教程中,ViewModels 总是扩展 android.arch.lifecycle.ViewModel 提供的 ViewModel 类。如果 viewModel 有参数,那么 Dagger 必须创建一个 ViewModelFactory 并将其注入到一个活动中

@Provides
@ActivityScope
fun provideViewModelFactory(dependency: Dependency) : ViewModelProvider.Factory = CustomViewModelFactory(dependency)

CustomViewModelFactory 将负责创建 ViewModel。这一切都很好,但是,当我可以将 viewModel 直接注入到类似这样的活动中时,我并没有真正理解 viewModelFactory 的观点:

@Module
class ViewModelModule(private val user: User) {
    @ActivityScope
    @Provides
    fun provideMainViewModel() = MainViewModel(user = user)
    fun provideOtherViewModel() = OtherViewModel()
}

@ActivityScope
@Subcomponent(modules = [ViewModelModule::class])
interface MainActivitySubComponent {
    fun inject(activity: MainActivity)
}

@ApplicationScope
@Component()
interface ApplicationComponent {
    fun addMainActivitySubComponent(viewModelModule: ViewModelModule) : MainActivitySubComponent
}

在我的活动中

class MainActivity : AppCompatActivity() {

    @Inject lateinit var viewModel: MainViewModel

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

        val subComponent = (application as MainApplication).component.addMainActivitySubComponent(ViewModelModule(User("NEW NAME")))

        subComponent.inject(this)
    }
}

那么,当我可以立即将 viewModel 注入到我的活动中时,ViewModelFactory 的意义何在?

【问题讨论】:

    标签: java android kotlin dagger-2


    【解决方案1】:

    让我们看看注入 ViewModel 时会发生什么:

    1. 您的 Activity 被(重新)创建。
    2. 您为所述活动创建一个(子)组件。
    3. 您注入依赖项。

    有趣的部分是 3,我们将在其中注入一些作用域对象(例如单例),但为我们的其余依赖项创建新对象。

    每次您(重新)创建 Activity(-> 配置更改)时,这些对象都会被再次创建,并且您将失去状态。你可以使用savedInstanceState 来保存一些数据,或者你可以想出一些其他的方法来保存状态(例如Singletons,retained Fragments,...)


    另一方面,ViewModel 承诺在方向变化之间保持状态。当我们在方向改变后从ViewModelProviders 请求 ViewModel 时我们将收到与以前相同的对象。我们无需担心保存和恢复状态。

    我们会重新创建工厂,但 Android/支持库/Jetpack/Arch 组件(无论现在叫什么)将存储 Viewmodel 并且仅在之前未创建它时创建它。以前的模型将在配置更改期间重复使用。


    因此,如果您想直接注入 ViewModel,您显然可以这样做,但您的 ViewModel 不会在方向更改之间保持其状态。

    【讨论】:

    • 所以如果我的应用程序的方向没有改变,一切都会正常工作吗?
    • @NaderBesada 这会令人困惑。使用 ViewModel 库但使用 ViewModel 库功能...没有什么意义。我建议按预期使用 ViewModel.Factory。
    • 方向改变不是唯一的配置改变。例如,您可以让用户更改语言,这也是配置更改。假设“没有发生任何配置更改,所以我应该完全忽略它们”不是一种安全的方法。
    【解决方案2】:

    您使用ViewModelProvidersViewModelProviders.Factory 来确保您在配置更改时获得相同的ViewModel 实例。所以在一个Activity的范围内,ViewModelProviders创建的ViewModel只创建一次。

    ViewModels 具有的 onCleared() 回调的预期行为也需要它。

    在 Kotlin 中,与多重绑定相比,我更喜欢使用 this linked approach。尽管它确实需要您了解可以创建视图模型的“注入器”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 2022-01-16
      • 1970-01-01
      • 2017-03-17
      • 2018-03-08
      • 1970-01-01
      相关资源
      最近更新 更多