Dagger2 преобразование в android.dagger
Я изучил некоторые учебники о новом подходе dagger.android, но не могу сделать это правильно. Я построил простое руководство с компоновщиком подкомпонентов, но я не могу преобразовать это в новый подход. Все учебники и статьи оставляют необходимые части пустыми.
Этот пример для целей обучения может не подходить для практических ситуаций, и я только намеревался реализовать внедрение в поле, внедрение в конструктор может быть более подходящим.
Объем
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
Родительский компонент
@Component(modules = ApplicationModule.class)
@Singleton
public interface ApplicationComponent {
// Calls SubComponent Builder from MainActivity using ApplicationComponent
ToastMakerSubComponent.Builder toastMakerBuilder();
}
Родительский модуль, я не использовал @BindsInstance в модуле приложения для изучения различных подходов
@Module(subcomponents = {ToastMakerSubComponent.class})
public class ApplicationModule {
private Context context;
public ApplicationModule(Context context) {
this.context = context;
}
@Provides
@Singleton
SharedPreferences provideSharedPreferences() {
System.out.println("ApplicationModule context: " + context);
return context.getSharedPreferences("PrefName", Context.MODE_PRIVATE);
}
}
Подкомпонент
@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent {
void inject(MainActivity mainActivity);
/*
Builder is called from Parent Component,
and parent component is called from scope(Activity, Fragment, etc.)
*/
@Subcomponent.Builder
interface Builder {
ToastMakerSubComponent build();
@BindsInstance
Builder context(Context context);
}
}
Подкомпонентный модуль
@Module
public class ToastMakerModule {
@ActivityScope
@Provides
ToastMaker provideToastMaker(Context context) {
System.out.println("ToastMakerModule context: " + context);
return new ToastMaker(context);
}
}
Создание экземпляра ApplicationComponent внутри MyApplication
mApplicationComponent = DaggerApplicationComponent
.builder()
.applicationModule(new ApplicationModule(getApplicationContext()))
.build();
И получить подкомпонент внутри Activity
ApplicationComponent applicationComponent = ((MyApplication) getApplication()).getApplicationComponent();
ToastMakerSubComponent toastMakerSubComponent = applicationComponent
.toastMakerBuilder()
.context(this)
.build();
toastMakerSubComponent.inject(this);
После этого, этого и этого урока я построил следующее как
@Component(modules = ApplicationModule.class)
@Singleton
public interface ApplicationComponent {
// What should i put here ???
}
Родительский модуль, но я не понял, как мне предоставить provideSharedPreferences
@Module(subcomponents = {ToastMakerSubComponent.class})
abstract class ApplicationModule {
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends MainActivity>
bindYourActivityInjectorFactory(ToastMakerSubComponent.Builder builder);
}
Подкомпонент отсутствует ToastMakerSubComponent build();
а также @BindsInstance Builder context(Context context);
как я должен добавить это к этому компоненту.
@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent extends AndroidInjector<MainActivity> {
// ??? Is this required?
void inject(MainActivity mainActivity);
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
???
}
}
Также я вижу @ContributesAndroidInjector
где это вписывается в этот пример?
1 ответ
Вот разница изменений: https://www.diffchecker.com/3IL8UQ7P
Расширить компонент приложения AndroidInjector<MyApplication>
и включать AndroidSupportInjectionModule
@Component(modules = {ApplicationModule.class, AndroidSupportInjectionModule.class})
@Singleton
public interface ApplicationComponent extends AndroidInjector<MyApplication> {
}
Расширить подкомпонент AndroidInjector<MainActivity>
и строитель AndroidInjector.Builder<MainActivity>
использовать seedInstance
предоставить аргументы @BindsInstance
методы.
@ActivityScope
@Subcomponent(modules = {ToastMakerModule.class})
public interface ToastMakerSubComponent extends AndroidInjector<MainActivity> {
@Subcomponent.Builder
abstract class Builder extends AndroidInjector.Builder<MainActivity> {
@Override
public void seedInstance(MainActivity instance) {
context(instance);
}
@BindsInstance
public abstract Builder context(Context context);
}
}
Добавьте привязку для компоновщика подкомпонента к модулю, установленному в компоненте приложения:
@Module(subcomponents = {ToastMakerSubComponent.class})
public abstract class ApplicationModule {
private Context context;
public ApplicationModule(Context context) {
this.context = context;
}
@Provides
@Singleton
SharedPreferences provideSharedPreferences() {
System.out.println("ApplicationModule context: " + context);
return context.getSharedPreferences("PrefName", Context.MODE_PRIVATE);
}
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity> bindMainActivityFactory(ToastMakerSubComponent.Builder builder);
}
Пусть каркасные классы расширяют Dagger*
коллеги или реализовать Has*Injector
интерфейсы, если вы не можете использовать наследование
public class MyApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerApplicationComponent.create();
}
}
public class MainActivity extends DaggerAppCompatActivity {
@Inject
SharedPreferences sharedPreferences;
@Inject
ToastMaker toastMaker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toastMaker.showToast("sharedPreferences " + sharedPreferences);
}
}