在将ViewModels注入(inject)到我的 Activity /片段中时,我注意到了一个奇怪的行为(遵循GithubBrowserSample的示例)。

试用1 起初,我只是懒洋洋地看到当我使用时会发生什么

@Inject MainViewModel viewModel;

显然,对于每个 Activity 以及旋转时,我都有一个MainViewModel的新实例。

试用2
然后,我更新为使用“正确的方式”注入(inject)ViewModelProvider.Factory并在onCreate中获取 View 模型:
@Inject ViewModelProvider.Factory viewModelProviderFactory;
private MainViewModel viewModel;

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

此代码段的工作原理很吸引人。打印viewModel将显示我从startActivity调用触发的每个新 Activity 实例中获得了一个新实例,但在旋转时可以重新使用。这让我开始思考...也许我可以注入(inject)MainViewModel。

试用版3 我更新了MainActivityModule,使其包括以下内容:
@Provides @ActivityScope
public MainViewModel provideMainViewModel(MainActivity activity,
        ViewModelProvider.Factory factory) {
    return ViewModelProviders.of(activity, factory).get(MainViewModel::class);
}

这甚至在屏幕旋转时也产生了MainViewModel的新实例(与试验1相同)。我验证了所提供的ViewModelProvider.Factory实例在每次调用ProvideMainViewModel时都相同。我还尝试删除了@ActivityScope,它甚至导致了更奇怪的行为,尤其是当尝试在MainActivity和MainFragment1中都包含MainViewModel的相同实例时。该片段获得了与旋转之前相同的MainViewModel实例,但是 Activity 获得了一个全新的实例,即使两个对ProvideMainViewModel的调用都使用MainActivity和工厂的相同实例进行了调用。

问题有人可以解释吗?我没有办法将ViewModel直接注入(inject)到我的 Activity /片段中吗?

更新

这真的让我感到困惑,因此我进行了更新,以包含问题HERE的完整示例。请注意,我必须更新AppInjector的FragmentLifecycleCallback才能在onFragmentPreCreated期间注入(inject)片段。这是由于片段的生命周期而完成的,使用SearchFragmentSearchViewModel中看到的当前实现将在onActivityCreated期间获取 View 模型的实例,该实例可以在同一片段上被多次调用。在这种情况下,将从ViewModelProviders返回相同的 View 模型,并将注册多个观察者。相反,应该在onCreate之前注入(inject)Fragment,并且应该在该点注册任何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

最佳答案

我可能是错的,但是由于Factory是在ActivityScope级别进行注释的,因此 Activity 的每个新实例将具有不同的提供程序实例,而该提供程序又将创建 View 模型的新实例。我将注入(inject)Factory,在ApplicationScope上对其进行注释(因为我们希望保留),然后使用它来获取 View 模型的实例。

关于android - Dagger 2注入(inject)ViewModel异常行为(ViewModel在屏幕旋转时未重复使用),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47874391/

10-09 17:52
查看更多