在将 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/