this可能重复
我正在用dagger2探索android注射api。因此,在我的示例应用程序中,我直接在活动中注入了ViewModel
;看看下面的代码片段。
class SampleApp : Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
override fun activityInjector(): AndroidInjector<Activity> =
dispatchingAndroidInjector
override fun onCreate() {
super.onCreate()
DaggerApplicationComponent.builder()
.application(this)
.build()
.inject(this)
}
}
@Component(modules = [
AndroidInjectionModule::class,
ActivityBindingModule::class,
AppModule::class
/** Other modules **/
])
@Singleton
interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun build(): ApplicationComponent
}
fun inject(sampleApp: SampleApp)
}
@Module
public abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = MainModule.class)
public abstract MainActivity contributeMainActivityInjector();
}
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mainViewModel: mainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
}
}
@Module
public class MainModule {
@Provides
public static MainViewModelProviderFactory provideMainViewModelProviderFactory(/** some dependencies **/) {
return new MainViewModelProviderFactory(/** some dependencies **/);
}
@Provides
public static MainViewModel provideMainViewModel(MainActivity activity, MainViewModelProviderFactory factory) {
return ViewModelProviders.of(activity, factory).get(MainViewModel.class);
}
}
如你所见,我已将MainViewModel
直接注入活动中。现在,如果我旋转活动,则注入的实例是不同的。
但是,如果我在MainViewModelProviderFactory
注入MainActivity
并执行
ViewModelProviders.of(activity, factory).get(MainViewModel.class)
它返回与以前相同的实例。
我没有弄到我的实施有什么问题。
任何指针都会很明显。
所以经过ViewModelProvider
,ViewModelProviders
,FragmentActivity
的来源,是的dagger2 documentation
我有一个答案..
如果我错了,请随意纠正我。
我们不能直接注入ViewModel,我们应该注入工厂。
由于这条线AndroidInjection.inject(this)
,我正面临这个问题。
根据匕首作者
在Activity中的super.onCreate()之前调用AndroidInjection.inject()至关重要
让我们看看这里出现了什么问题。
活动将使用ViewModel
保留它的旋转onRetainNonConfigurationInstance
并将在onCreate()
恢复它
正如我们在调用super.onCreate()
之前注入的那样,我们不会得到保留的MainViewModel
对象而是新的对象。
如果您需要详细信息,请继续阅读..
当匕首试图注入MainViewModel
时,它调用provideMainViewModel()
的MainModule
方法,调用以下表达式(请记住super.onCreate()
尚未调用)
ViewModelProviders.of(activity, factory).get(MainViewModel.class)
ViewModelProviders.of
将返回一个ViewModelProvider
,其中包含各自活动和ViewModelStore
的ViewModelProviderFactory
的参考
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
.
.
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
qazxsw poi将最终打电话给活动qazxsw poi,因为在这种情况下的活动是ViewModelStore.of(activity)
实施getViewModelStore()
qazxsw poi创建新的qazxsw poi,如果它为null或持有它的引用。 AppCompatActivity
是ViewModelStoreOwner
的包装,另外还有AppCompatActivity
方法
ViewModelStore
只要设备被旋转,活动就会使用ViewModelStore
保留它的非配置实例状态,并在Map<String, ViewModel>
中恢复它。
clear()
将尝试从活动的@NonNull
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.");
} else {
if (this.mViewModelStore == null) {
this.mViewModelStore = new ViewModelStore();
}
return this.mViewModelStore;
}
}
获取onRetainNonConfigurationInstance
onCreate
在这个特定的例子中;因为我们还没有调用ViewModelProvider.get
方法,但实现将要求ViewModel
创建它并将更新相应的ViewModelStore
。
因此我们最终得到了两个不同的public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
对象。