简体   繁体   English

如何在 SavedStateHandle 感知 AndroidViewModel 中注入依赖项?

[英]How to inject dependencies in a SavedStateHandle-aware AndroidViewModel?

Assume a view model like this:假设像这样的视图 model :

public class FooViewModel extends AndroidViewModel {

    @Inject public FooViewModel(Application app, SavedStateHandle handle, Bar bar) {
        // ...
    }
}

I want to inject Bar using Dagger 2. I am developing on Android.我想使用 Dagger 2 注入Bar 。我正在 Android 上进行开发。

According to the SavedStateHandle docs :根据SavedStateHandle文档

You should use SavedStateViewModelFactory if you want to receive this object in ViewModel 's constructor.如果你想在ViewModel的构造函数中接收这个 object ,你应该使用SavedStateViewModelFactory

However, the SavedStateViewModelFactory docs state that the factory is final which means I cannot inject Bar there, either.但是, SavedStateViewModelFactory文档state 工厂是final的,这意味着我也不能在那里注入Bar

So far, I have been injecting via a setter:到目前为止,我一直在通过 setter 进行注入:

    @Provides
    FooViewModel provideFooViewModel(ViewModelStoreOwner owner, Bar bar) {
        FooViewModel viewModel = new ViewModelProvider(owner).get(FooViewModel.class);

        viewModel.setBar(bar);

        return viewModel;
    }

Is there a better way to do this?有一个更好的方法吗?

I want to use constructor injection, mark the Bar instance variable as final and eliminate the setter.我想使用构造函数注入,将Bar实例变量标记为final并消除 setter。

To provide a FooViewModel , you need a custom implementation of AbstractSavedStateViewModelFactory .要提供FooViewModel ,您需要AbstractSavedStateViewModelFactory的自定义实现。

MyComponent component = DaggerMyComponent.withViewModelStoreOwner(this)
.withSavedStateRegistryOwner(this)
.withDefaultArguments(this.arguments != null ? this.arguments : new Bundle())
.build();

and

    @Provides
    @Suppress("UNCHECKED_CAST")
    public MyViewModel viewModel(ViewModelStoreOwner viewModelStoreOwner, SavedStateRegistryOwner savedStateRegistryOwner, Bundle defaultArgs, Application application, Bar bar) {
        return new ViewModelProvider(
            viewModelStoreOwner,
            new AbstractSavedStateViewModelFactory(savedStateRegistryOwner, defaultArgs) {
                @Override
                public <T extends ViewModel> T create(
                    String key,
                    Class<T> modelClass,
                    SavedStateHandle handle) {
                    return (T) new MyViewModel(application, handle, bar);
                } 
            }).get(MyViewModel.class);
        });
    }

Note:笔记:

1.) you only get SavedStateHandle inside the AbstractSavedStateViewModelFactory , so you won't be able to get it into your graph. 1.)您只能在AbstractSavedStateViewModelFactory中获得SavedStateHandle ,因此您将无法将其放入您的图表中。

2.) you can reduce the length of that provider by using https://github.com/square/AssistedInject . 2.) 您可以使用https://github.com/square/AssistedInject来缩短该提供程序的长度。 Theoretically AutoFactory would also work, but it seems unmaintained in comparison.理论上 AutoFactory 也可以工作,但相比之下似乎没有维护。

3.) you won't be able to get @Inject on your ViewModel. 3.) 您将无法在 ViewModel 上获得@Inject

This answer was partly adapted from https://github.com/Zhuinden/DaggerViewModelExperiment/blob/c3cbf0a5bc85467cec08755fcc152db5e8c55f91/app/src/main/java/com/zhuinden/daggerviewmodelexperiment/features/second/SecondFragment.kt#L32-L47 .该答案部分改编自https://github.com/Zhuinden/DaggerViewModelExperiment/blob/c3cbf0a5bc85467cec08755fcc152db5e8c55f91/app/src/main/java/com/zhuinden/daggerviewSecdFragment/kont#L32/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM