android - Dagger 2 注入(inject) ViewModel 异常行为(ViewModel 未在屏幕旋转时重新使用)

标签 android mvvm android-lifecycle dagger-2

在将 ViewModel 注入(inject)我的 Activity/fragment 时,我注意到一个奇怪的行为(遵循 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 相同)。我验证了每次调用 provideMainViewModel 时提供的 ViewModelProvider.Factory 实例都是相同的。我还尝试删除 @ActivityScope,这会导致更奇怪的行为,尤其是当试图在 MainActivity 和 MainFragment1 中包含相同的 MainViewModel 实例时。该 fragment 获得了与旋转之前相同的 MainViewModel 实例,但 Activity 获得了一个全新的实例,即使对 provideMainViewModel 的两次调用都是使用相同的 MainActivity 实例和工厂调用的。

问题 谁能解释一下?我没有办法将 ViewModel 直接注入(inject)到我的 Activity/fragment 中吗?

更新

这真的让我感到困惑,所以我已经更新以包含问题的完整示例 HERE .请注意,我必须更新 AppInjector 的 FragmentLifecycleCallback 以在 onFragmentPreCreated 期间注入(inject) fragment 。这是由于 fragment 的生命周期而完成的,在 SearchFragment 中看到的当前实现使用 SearchViewModel 将在 onActivityCreated 期间获取 View 模型的实例可以在同一个 fragment 上多次调用。在这种情况下,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

最佳答案

我可能是错的,但是因为工厂是在 ActivityScope 级别注释的,所以 Activity 的每个新实例都会有一个不同的提供者实例,这又会创建一个新的 View 模型实例。我会注入(inject)工厂,在 ApplicationScope 对其进行注释(因为我们希望保留),然后使用它来获取 View 模型的实例。

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

相关文章:

c# - 在另一个类 MVVM 中调用 RelayCommand

c# - 关于使用 Caliburn.Micro MVVM WPF 进行 View 导航的建议

android - 如何只用一个形状绘制多色线

android - GWT 应用程序在 Android 浏览器中运行良好吗?

java - Android - 如何将不同的图像资源放入 SimpleAdapter?

android - 通过 mvvm android 处理异常

android - 我什么时候可以首先测量 View ?

android - 带有计时器的服务调用另一个服务

android - 如何杀死 Activity 的特定实例?

android - Oreo (8.1) 上的 toast 重叠问题