Dagger 2注入ViewModel奇怪的行为(ViewModel在屏幕旋转时没有重复使用)

时间:2017-12-18 18:29:48

标签: android mvvm android-lifecycle dagger-2

我注意到在将ViewModel注入我的活动/片段时出现奇怪的行为(遵循GithubBrowserSample处的示例)。

试用1 起初我只是懒得看看使用时会发生什么

@Inject MainViewModel viewModel;

显然,我为每个活动和旋转时都获得了MainViewModel的新实例。

试用2 然后我更新为使用“正确的方式”注入ViewModelProvider.Factory并抓取onCreate中的视图模型:

@Inject ViewModelProvider.Factory viewModelProviderFactory;
private MainViewModel viewModel;

@Override
public void onCreate(Bundle savedInstanceState) {
    viewModel = ViewModelProviders.of(this, viewModelProviderFactory)
            .get(MainViewModel::class);
}

这个片段就像一个魅力。打印viewModel将显示我为从startActivity调用触发但在旋转时重新使用的每个新活动实例获取新实例。这让我想到了...也许我可以注入MainViewModel。

试用版3 我更新了我的MainActivityModule以包含以下内容:

@Provides @ActivityScope
public MainViewModel provideMainViewModel(MainActivity activity,
        ViewModelProvider.Factory factory) {
    return ViewModelProviders.of(activity, factory).get(MainViewModel::class);
}

这导致了MainViewModel的新实例,即使在屏幕旋转上也是如此(与试验1相同)。我验证了每次调用provideMainViewModel时提供的ViewModelProvider.Factory实例都是相同的。我还尝试删除@ActivityScope,这会导致更奇怪的行为,尤其是在尝试在MainActivity和MainFragment1中包含相同的MainViewModel实例时。该片段获得了与旋转之前相同的MainViewModel实例,但是活动得到了一个全新的,即使调用了provideMainViewModel都使用相同的MainActivity实例和工厂调用。

问题任何人都可以解释一下吗?我没办法将ViewModel直接注入我的activity / fragment吗?

更新

这真让我感到困惑所以我已经更新,以包含问题HERE的完整示例。请注意,我必须更新AppInjector的FragmentLifecycleCallback以在onFragmentPreCreated期间注入片段。这是由于片段的生命周期而完成的,使用SearchFragmentSearchViewModel中看到的当前实现将在onActivityCreated期间获取视图模型的实例,该实例可能会被调用多次相同的片段。在这种情况下,将从ViewModelProviders返回相同的视图模型,并将注册多个观察者。而应该在onCreate之前注入片段,并且应该在那时注册任何LiveData观察者。

运行并旋转时,您将看到以下日志:

12-19 22:48:28.538 7116-7116/com.android.example.github D/MainActivityProvidersMo: provideMainViewModel for com.android.example.github.MainActivity@78c5d27 using com.android.example.github.viewmodel.GithubViewModelFactory@6d6c140: com.android.example.github.MainViewModel@fd1f879
12-19 22:48:28.611 7116-7116/com.android.example.github D/MainActivity: viewModel: com.android.example.github.MainViewModel@fd1f879
12-19 22:48:28.615 7116-7116/com.android.example.github D/dagger.android.support: An injector for com.android.example.github.ui.search.SearchFragment was found in com.android.example.github.MainActivity
12-19 22:48:28.616 7116-7116/com.android.example.github D/SearchFragment: mainViewModel: com.android.example.github.MainViewModel@fd1f879
12-19 22:48:28.760 7116-7116/com.android.example.github D/SearchFragment: results live data has observers? false


12-19 22:48:40.579 7116-7116/com.android.example.github D/MainActivityProvidersMo: provideMainViewModel for com.android.example.github.MainActivity@d1f344f using com.android.example.github.viewmodel.GithubViewModelFactory@6d6c140: com.android.example.github.MainViewModel@c5387dc
12-19 22:48:40.581 7116-7116/com.android.example.github D/dagger.android.support: An injector for com.android.example.github.ui.search.SearchFragment was found in com.android.example.github.MainActivity
12-19 22:48:40.583 7116-7116/com.android.example.github D/SearchFragment: mainViewModel: com.android.example.github.MainViewModel@c5387dc
12-19 22:48:40.625 7116-7116/com.android.example.github D/MainActivity: viewModel: com.android.example.github.MainViewModel@c5387dc
12-19 22:48:40.715 7116-7116/com.android.example.github D/SearchFragment: results live data has observers? false

1 个答案:

答案 0 :(得分:0)

我可能错了,但由于Factory在ActivityScope级别进行了注释,因此每个活动的新实例都会有一个不同的提供者实例,而后者将创建一个新的视图模型实例。我会注入Factory,在ApplicationScope上注释它(因为我们希望保留),然后用它来获取视图模型的实例。