Rup*_*esh 2 android kotlin dagger-2 android-mvvm android-architecture-components
可能重复此
我正在用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)
}
}
Run Code Online (Sandbox Code Playgroud)
@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)
}
Run Code Online (Sandbox Code Playgroud)
@Module
public abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = MainModule.class)
public abstract MainActivity contributeMainActivityInjector();
}
Run Code Online (Sandbox Code Playgroud)
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mainViewModel: mainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dashboard)
}
}
Run Code Online (Sandbox Code Playgroud)
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我已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对象而是新的对象.
如果您需要详细信息,请继续阅读..
当dagger尝试注入MainViewModel时调用provideMainViewModel()方法MainModule,调用以下表达式(请记住super.onCreate()尚未调用)
ViewModelProviders.of(activity, factory).get(MainViewModel.class)
Run Code Online (Sandbox Code Playgroud)
该ViewModelProviders.of会返回一个ViewModelProvider保存用于该引用ViewModelStore各自活动和ViewModelProviderFactory
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
.
.
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
Run Code Online (Sandbox Code Playgroud)
ViewModelStore.of(activity)最终会给活动打电话,getViewModelStore()因为在这种情况下,活动是AppCompatActivity实施的ViewModelStoreOwner
AppCompatActivityViewModelStore如果它为null,则创建new 并保存对它的引用.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;
}
}
Run Code Online (Sandbox Code Playgroud)
每当设备被旋转时,活动将保留其非配置实例状态,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;
}
Run Code Online (Sandbox Code Playgroud)
在这个特定的例子中; 因为我们还没有调用super.onCreate()方法,实现将要求factory创建它并将更新相应的ViewModelStore.
因此我们最终得到了两个不同的MainViewModel对象.
| 归档时间: |
|
| 查看次数: |
977 次 |
| 最近记录: |